Compare commits

...

73 Commits

Author SHA1 Message Date
0e4eb976e1 export nits
- XLSX write dense mode null check (fixes #3261 h/t @mbornstein)
- Use `subarray` for Uint8Array/Buffer ops (h/t @hardonthebeat)
2025-02-22 15:18:51 -05:00
9c3853ba25 fix: missing break condition in make_json_row 2025-01-10 16:26:17 +05:30
318e2319ee ODS parse hyperlink tooltips 2024-11-10 21:27:04 -05:00
6c0f950f83 feat: Add Sheet Protection for XLS (BIFF8) (#3202)
Fixes #3201

Reviewed-on: #3202
Co-authored-by: Lucas Picchi <lucas.picchi@exeo.com.ar>
Co-committed-by: Lucas Picchi <lucas.picchi@exeo.com.ar>
2024-10-26 20:37:20 +00:00
235ed7ccfb update CONTRIBUTING.md (fixes #3233 h/t @Akxe) 2024-10-21 09:43:40 -04:00
2d6c821261 Parse DIF-esque CSV (fixes #3230 h/t @lowkeyfish) 2024-10-02 01:04:56 -04:00
36debb0eaa RollupJS workaround (fixes #3219 h/t @lvzhenbo) 2024-09-19 19:45:18 -04:00
df48a059c3 Ignore negative sign for a symmetric rounding. 2024-09-18 17:31:02 -07:00
647cdb89f5 Add test files to .gitignore 2024-09-09 18:14:32 -03:00
6912bdb2d4 fix: Add DenseSheetData type (#3195) 2024-09-05 10:25:52 +08:00
5550b90704 fix: infinite loop due to hidden row in XLSX.stream.to_json (#3178)
**Title:**

Fix for Incorrect Row Indexing and Infinite Loop in stream.to_json Function

**Description:**

This pull request addresses two key issues in the `stream.to_json` function of the SheetJS library:

1. **Infinite Loop**: Previously, when a row was hidden, the function skipped processing the current row without incrementing the row counter `R`, resulting in an infinite loop during execution.

2. **Incorrect Row Indexing**: The row index was incorrectly accessed using a one-based index, whereas the actual row index was zero-based. This led to unintended hidden rows being included in the stream and skipping of subsequent non-hidden rows.

**Changes:**

- Modified the hidden row check to use the correct zero-based indexing
- Incremented `R` after identifying a hidden row to ensure the loop progresses to the next row.
- Ensured that the stream correctly processes all rows, skipping hidden rows without affecting subsequent rows.

**Testing:**

- Validated that the `stream.to_json` function no longer enters an infinite loop when encountering hidden rows.
- Confirmed that the correct rows are processed and pushed to the stream, with hidden rows being appropriately skipped.

**Impact:**

This fix enhances the reliability of the SheetJS library, ensuring accurate data streaming from spreadsheets without infinite loops or incorrect row handling.

**Checklist:**

- [x] Code changes have been tested locally.
- [x] The changes adhere to the project's coding standards and guidelines.

**Additional Information:**

These changes are crucial for maintaining the library's functionality in production environments, where precise data handling is essential.

**References:**

Closes #3176.

---

Reviewed-on: #3178
Co-authored-by: deepak-negi-web <deepak-negi-web@noreply.git.sheetjs.com>
Co-committed-by: deepak-negi-web <deepak-negi-web@noreply.git.sheetjs.com>
2024-08-21 05:34:31 +00:00
9368a85b5f XLSX encoded entities (fixes #3177)
- HTML DOM ingress support formulae (`data-f`)
- Sheet Visibility for ODS / FODS (fixes #3162)
2024-08-19 12:43:37 -04:00
2669c7cf1c actually remove test_files submodule 2024-07-19 14:57:19 -04:00
b61eed74fc do not bail when XLS properies cannot be parsed 2024-07-17 14:23:02 -04:00
8a7cfd47bd version bump 0.20.3 2024-07-12 11:47:14 -04:00
f215b8f79f merge nits (fixes #3142 h/t @s-ashwin ) 2024-07-11 01:33:25 -04:00
5a36cb423d NaN and Infinity error export
- `read` handle `Int8Array` (to support Java engines)
- `sheet_to_formulae` option to suppress values
- handle unexpected `<charset/>` (fixes #3143 h/t @dearzubi)
2024-07-04 15:54:34 -04:00
5ef49e2b96 XLML Streaming Write
- CSV Export only quote leading ID (fixes #2959)
2024-05-31 03:16:53 -04:00
947a5178bd ssf format NaN and Infinity values 2024-04-27 19:49:12 -04:00
87a695747e docs: ✏️ Fixed broken links in contributing.md 2024-04-10 02:09:14 -07:00
a0bed2a97d version bump 0.20.2
see https://regexide.com for more details
2024-04-04 21:30:28 -04:00
0941ff97a3 dta v0.0.2 2024-03-22 00:39:09 -04:00
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
d4d4ff3da2 SYLK error cells read/write (fixes #3049) 2024-01-10 04:54:10 -05:00
29d46c07a8 version bump 0.20.1 2023-12-05 03:19:42 -05:00
9199c2600c dta initial 2023-11-13 06:13:07 -05:00
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
ad0fb7766b import and export blank worksheets 2023-10-17 04:53:37 -04:00
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
432ac1fda7 xlsx-cli v1.1.4 2023-10-11 16:22:42 -04:00
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
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
485a4f30f1 set CSV formula cell value to raw fmla text 2023-08-23 13:38:14 -04:00
68cce77d23 package.json exports (fixes #2977 h/t @stof) 2023-08-20 21:01:07 -04:00
c0b9e229a0 Delete .github/ISSUE_TEMPLATE/config.yml 2023-08-18 15:26:54 +00:00
955543147d version bump 0.20.0 2023-06-23 05:48:47 -04:00
36c5b7c0f5 NUMBERS read/write threaded comments 2023-06-14 03:47:51 -04:00
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
d3a480750b NUMBERS read/write external links 2023-05-13 01:23:26 -04:00
5b33acfaf4 parse self-closing text:p uof:文本串 (fixes #2927) 2023-04-30 03:57:30 -04:00
b68eaed726 Export NaN/Infinity to error cells (fixes #2897) 2023-04-23 03:58:36 -04:00
333e4e40f9 version bump 0.19.3 2023-04-17 23:39:28 -04:00
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
c06a32043f Add ESM helper methods to CJS build (fixes #2909) 2023-04-10 01:15:44 -04:00
ffbea71bc2 XLS ExternSheet record (fixes #2907) 2023-04-05 15:34:55 -04:00
16dd8a6eae UTF16LE sans codepage (fixes #2898 h/t @brismuth) 2023-03-15 04:17:09 -04:00
0577bb7a45 version bump 0.19.2 2023-01-25 16:17:34 -05:00
b150dea21d denoized otorp [ci skip] 2023-01-06 02:37:53 -05:00
e9cf1ad0fb ignore unexpected attributes in rich text part
Co-authored-by: colin4 <colin4@noreply.sheetjs.com>
2023-01-04 12:35:13 -05:00
5141222c24 sheet_to_json type include origin option
Co-authored-by: Hulusi <chsdwn@noreply.sheetjs.com>
2023-01-01 16:53:44 -05:00
51a8619000 version bump 0.19.1 2022-11-17 04:35:34 -05:00
e7e129e417 type fix (fixes #2828 h/t @younes-io) 2022-11-16 14:03:42 -05:00
df48489211 Numbers 12.2 skip ActivityStream.iwa 2022-11-06 21:58:41 -05:00
050f66ce1b version bump 0.19.0 2022-10-23 21:05:59 -04:00
2f329b64e2 DBF truncate numeric fields 2022-10-04 20:09:43 -04:00
515d1c6f2e mini refresh [ci skip] 2022-10-04 16:50:55 -04:00
654d6f98c3 stringify all 's' cell values (fixes #2795) 2022-09-28 23:08:10 -04:00
4ae4f0fad9 NUMBERS write multiple worksheets [ci skip] 2022-09-26 13:52:50 -04:00
Evan Bovie
1ca49a50bd
add display property to XLSX hyperlinks (#2791)
Resolves import bug in Google Sheets
2022-09-23 13:36:38 -04:00
81b231d866 version bump 0.18.12 2022-09-22 05:06:45 -04:00
1491302aa4 package.json exports types 2022-09-21 18:17:14 -04:00
bd5878e7c7 NUMBERS write up to ALL1000000 (h/t @masaccio) 2022-09-20 01:35:34 -04:00
Evan Bovie
4dd092a076 Add types to subpath exports in package.json 2022-09-18 23:26:24 -04:00
390910131
04dc18e742
fix vue3-table-lite demo url typo 2022-09-13 13:58:09 +08:00
6a5be04e3d Ś╫êëτ⌡ś and Š╫ěéτ⌡š 2022-09-09 16:59:22 -04:00
e90a61bf09 version bump 0.18.11 2022-09-06 02:18:12 -04:00
26cbfe37be DBF write encoding (fixes #2781 h/t @ZJS248) 2022-09-06 00:02:39 -04:00
df0e7b5f25 NUMBERS duration cell number format 2022-09-04 17:51:49 -04:00
6c9010f9d1 comment fallback (fixes #2779 h/t @AbhinanduReddy) 2022-09-02 03:30:10 -04:00
0a6ddcaf44 removed sheet_to_dif IIFE 2022-08-30 03:00:32 -04:00
194 changed files with 39087 additions and 20148 deletions

@ -11,6 +11,7 @@
"comma-dangle": [ 2, "never" ],
"curly": 0,
"no-bitwise": 0,
"no-cond-assign": 1,
"no-console": 0,
"no-control-regex": 0,
"no-unused-vars": 1,

7
.gitignore vendored

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

3
.gitmodules vendored

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

@ -11,6 +11,7 @@ node_modules
*.jsx
_book
book.json
v8.log
tmp
*.[tT][xX][tT]
*.[cC][sS][vV]
@ -19,6 +20,7 @@ tmp
*.[pP][mM][dD]*
*.[pP][dD][fF]
*.[sS][lL][kK]
*.[sS][yY][lL][kK]
*.socialcalc
*.[xX][lL][sSwWcCaAtTmMrR]
*.[xX][lL][sSaAtT][xXmMbB]
@ -32,6 +34,7 @@ tmp
*.[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]
@ -58,11 +61,11 @@ make.cmd
xlsworker.js
shim.js
test.js
hotcross.mjs
test.mjs
test.ts
test.mts
testnocp.ts
testbun.mjs
.jscs.json
.gitmodules
.travis.yml

@ -54,6 +54,7 @@ Rollup
SessionStorage
SQLite
SystemJS
Vite
VueJS
WebKit
WebSQL

@ -4,6 +4,79 @@ This log is intended to keep track of backwards-incompatible changes, including
but not limited to API changes and file location changes. Minor behavioral
changes may not be included if they are not expected to break existing code.
* Sheet Visibility for ODS / FODS (h/t @edemaine)
* HTML DOM ingress support formulae (`data-f`)
* Proper handling of XLSX encoded entities (h/t @inreoh)
* Proper handling of invalid DIF sheets that match heuristics (h/t @lowkeyfish)
## v0.20.3
* Correct parsing of NUMBERS and ODS merge cells (h/t @s-ashwin)
* More precise treatment of infinite and NaN values
* XLML Streaming Write
* Parse `Int8Array` objects (for compatibility with JS engines in Java)
* CSV Export only quote leading ID (h/t @lako12)
## v0.20.2
* Reworked parsing methods to avoid slow regexes (CVE-2024-22363)
* HTML properly encode data-v attribute
* SYLK read and write error cells
## v0.20.1
* `init` use packaged test files to work around GitHub breaking changes
* SSF date code rounding to 15 decimal digits (h/t @davidtamaki)
* `sheet_to_json` force UTC interpretation for formatted strings (h/t @Blanay)
* QPW extract result of string formula
* XLSX parse non-compliant merge cell expressions
* NUMBERS correctly handle rows omitted from official exports
* DBF parse empty logical field (h/t @Roman91)
* `dense` option added to types
* package.json add mini and core scripts to export map (h/t @stof)
## v0.20.0
* Use UTC interpretation of Date objects for date cells (potentially breaking)
* API functions support UTC and local time value interpretations
* Export `NaN` values to `#NUM!` and infinite values to `#DIV/0!`
## v0.19.3
* XLSX Ensure comment address is valid (h/t @slonser)
* Enforce Excel worksheet name restrictions
* Fixed "Prototype Pollution" vulnerability (CVE-2023-30533)
## v0.19.2
* XLSX proper decoding of hyperlinks (h/t @tw-yaxu)
* XLSX ignore unexpected attributes in rich text (h/t @colin4)
* `sheet_to_json` type fix (h/t @chsdwn)
## v0.19.1
* Fixed types issue in strict mode (h/t @younes-io)
* Numbers 12.2 parsing skip ActivityStream.iwa
## v0.19.0
* XLSX export hyperlinks compatible with google sheets (h/t Evan Bovie)
* NUMBERS export multiple sheets, full worksheet range
* formalized `dense` mode
## v0.18.12
* `package.json` added types in `exports` structure
* uncapped NUMBERS single-sheet single-table export
* DBF export records using supported codepages
## v0.18.11
* Base64 input ignore data URI wrapper
* Parse ZIP files that use ZIP64 extended information field
* More precise handling of time-only values
* Threaded Comment fallback text for older Excel
## v0.18.10
* `exports` field in package.json to satiate ViteJS and newer tooling
@ -21,7 +94,7 @@ changes may not be included if they are not expected to break existing code.
## v0.18.8
* Plaintext parsing of dateless meridien time values (`1:23:45 PM`)
* Legacy format (SYLK / WK# / Multiplan) minutiae
* Legacy format (SYLK / WK# / Multiplan) minutiae
## v0.18.7

@ -1,70 +1,74 @@
# Contributing
The SheetJS Libraries should be free and clear to use in your projects. In
order to maintain that, every contributor must be vigilant.
SheetJS CE should be free and clear to use in your projects. To ensure that
remains true, each contributor must be vigilant and each contribution must be
carefully scrutinized from a technical and legal perspective.
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.
Many commercial products and open source projects have been very lax regarding
licensing. They are ticking timebombs that no commercial product should use.
# Required Reading
## 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://web.archive.org/web/20200916173942/https://github.com/jazzband/tablib/issues/114
- http://www.codinghorror.com/blog/2007/04/pick-a-license-any-license.html
- https://web.archive.org/web/20240909210554/https://github.com/stephen-hardy/xlsx.js/issues/8
# Raising Issues
## Raising Issues
Issues should generally be accompanied by test files. Since github does not
support attachments, the best method is to send files to <sheetjs@gmail.com>
(subject line should contain issue number or message) or to share using some
storage service. Unless expressly permitted, any attachments will not be
shared or included in a test suite (although I will ask :)
Issues should generally be accompanied by test files. It is strongly recommended
to use the [issue tracker](https://git.sheetjs.com/sheetjs/sheetjs/issues).
If sending email to a gmail account is problematic, the <dev@sheetjs.com> email
inbox is self-hosted.
If they cannot be shared publicly, please send files to <oss@sheetjs.com>
(subject line should contain issue number or message) or share links to files
hosted on a storage service. Unless expressly permitted, attachments will not be
shared outside of SheetJS LLC or included in a test suite.
# Opening Pull Requests
If a NDA is required, please send an email to <oss@sheetjs.com> with subject
line "Non-Disclosure Agreemeant Request".
Before opening a pull request, [squash all commits into
one](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History). If the pull
request addresses documentation or demos, add `[ci skip]` in the body or title
of your commit message to skip Travis checks.
# Pre-Contribution Checklist
## Opening Pull Requests
Please raise an issue before opening pull requests. It is easy to solve a
specific problem without considering the full context or implications.
## Pre-Contribution Checklist
Before thinking about contributing, make sure that:
- You are not, nor have ever been, an employee of Microsoft Corporation.
- You have not signed any NDAs or Shared Source Agreements with Microsoft
Corporation or a subsidiary
Corporation or a subsidiary.
- You have not consulted any existing relevant codebase (if you have, please
take note of which codebases were consulted).
If you cannot attest to each of these items, the best approach is to raise an
issue. If it is a particularly high-priority issue, please drop an email to
<sheetjs@gmail.com> and it will be prioritized.
issue. If it is a particularly high-priority issue, please drop an email to
<support@sheetjs.com> and it will be prioritized.
# Intra-Contribution
## Intra-Contribution
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.
- Your contributions are your original work. Take note of any resources you
consult in the process. Be extra careful not to use unlicensed code on the
Internet or code generated by a large language model or other AI tool.
- You are working on your own time. Unless they explicitly grant permission,
- You are working on your own time. Unless they explicitly grant permission,
your employer may be the ultimate owner of your IP
# Post-Contribution
Before contributions are merged, you will receive an email (at the address
associated with the git commit) and will be asked to confirm the aforementioned
items. Ensure that the email addresses associated with the commits are valid.
## Post-Contribution
Before certain contributions are merged, you will receive an email (at the
address associated with the git commit) and will be asked to confirm the
aforementioned items. Ensure that the email addresses associated with the
commits are valid.

@ -67,10 +67,9 @@ clean-data:
.PHONY: init
init: ## Initial setup for development
git submodule init
git submodule update
#git submodule foreach git pull origin master
git submodule foreach make all
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
@ -107,12 +106,13 @@ dist-deps: ## Copy dependencies for distribution
.PHONY: aux
aux: $(AUXTARGETS)
BYTEFILEC=dist/xlsx.{full,core,mini}.min.js
BYTEFILER=dist/xlsx.extendscript.js xlsx.mjs
BYTEFILEC=dist/xlsx.{full,core,mini}.min.js xlsx.mjs
BYTEFILER=dist/xlsx.extendscript.js
.PHONY: bytes
bytes: ## Display minified and gzipped file sizes
@for i in $(BYTEFILEC); do 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
@ -140,6 +140,10 @@ test mocha: test.js ## Run test suite
#* 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 $<
@ -148,22 +152,27 @@ 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: hotcross.mjs ## Run Bun test suite
bun $<
test-bun: test.test.mjs ## Run Bun test suite
bun test $<
.PHONY: test-deno
test-deno: test.ts ## Run Deno test suite
deno test --allow-env --allow-read --allow-write --config misc/test.deno.jsonc $<
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 --allow-env --allow-read --allow-write --config misc/test.deno.jsonc $<
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_%:
@ -245,8 +254,7 @@ misc/coverage.html: $(TARGET) test.js
coveralls: ## Coverage Test + Send to coveralls.io
mocha --require blanket --reporter mocha-lcov-reporter -t 30000 | node ./node_modules/coveralls/bin/coveralls.js
DEMOMDS=$(sort $(wildcard demos/*/README.md))
MDLINT=$(DEMOMDS) README.md demos/README.md
MDLINT=README.md
.PHONY: mdlint
mdlint: $(MDLINT) ## Check markdown documents
./node_modules/.bin/alex $^

@ -9,35 +9,27 @@ 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!
[![License](https://img.shields.io/github/license/SheetJS/sheetjs)](https://github.com/SheetJS/sheetjs/blob/master/LICENSE)
[![Build Status](https://img.shields.io/github/workflow/status/sheetjs/sheetjs/Tests:%20node.js)](https://github.com/SheetJS/sheetjs/actions)
[![Snyk Vulnerabilities](https://img.shields.io/snyk/vulnerabilities/github/SheetJS/sheetjs)](https://snyk.io/test/github/SheetJS/sheetjs)
[![npm Downloads](https://img.shields.io/npm/dm/xlsx.svg)](https://cdn.sheetjs.com/)
[![GitHub Repo stars](https://img.shields.io/github/stars/SheetJS/sheetjs?style=social)](https://github.com/SheetJS/sheetjs)
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/sheetjs?pixel)](https://github.com/SheetJS/sheetjs)
[![Build Status](https://saucelabs.com/browser-matrix/sheetjs.svg)](https://saucelabs.com/u/sheetjs)
## Documentation
- [API and Usage Documentation](https://docs.sheetjs.com)
- [Downloadable Scripts and Modules](https://cdn.sheetjs.com)
## Related Projects
## Constellation
- <https://oss.sheetjs.com/notes/>: File Format Notes
- [`ssf`](packages/ssf): Format data using ECMA-376 spreadsheet format codes
- [`xlsx-cli`](packages/xlsx-cli/): NodeJS command-line tool for processing files
- [`xlsx-cli`](packages/xlsx-cli): NodeJS command-line tool for processing files
- [`test_files`](https://github.com/SheetJS/test_files): Sample spreadsheets
- [`cfb`](https://git.sheetjs.com/SheetJS/js-cfb): Container (OLE/ZIP) file
processing library
- [`cfb`](https://github.com/SheetJS/js-cfb): Container (OLE/ZIP) format library
- [`codepage`](https://git.sheetjs.com/SheetJS/js-codepage): Legacy text
encodings for XLS and other legacy spreadsheet formats
- [`codepage`](https://github.com/SheetJS/js-codepage): Legacy text encodings
- [`dta`](packages/dta): Stata DTA file processor
## License

@ -2,6 +2,7 @@
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* eslint-env node */
/* vim: set ts=2 ft=javascript: */
var n = "xlsx";
var X = require('../');
try { X = require('../xlsx.flow'); } catch(e) {}
@ -17,7 +18,7 @@ try { program = require('commander'); } catch(e) {
"For older versions of node, explicitly install `xlsx-cli` globally:",
" $ npm i -g xlsx-cli",
" $ xlsx-cli --help"
].forEach(function(m) { console.error(m); });
].forEach(function (m) { console.error(m); });
process.exit(1);
}
program
@ -65,9 +66,10 @@ program
.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('--date-format <string>', 'output date format, for example yyyy-mm-dd')
.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('-d, --no-dim', 'recalculate worksheet range')
.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')
@ -102,18 +104,18 @@ var wb_formats_2 = [
program.parse(process.argv);
var filename = '', sheetname = '';
if(program.args[0]) {
if (program.args[0]) {
filename = program.args[0];
if(program.args[1]) sheetname = program.args[1];
if (program.args[1]) sheetname = program.args[1];
}
if(program.sheet) sheetname = program.sheet;
if(program.file) filename = program.file;
if (program.sheet) sheetname = program.sheet;
if (program.file) filename = program.file;
if(!filename) {
if (!filename) {
console.error(n + ": must specify a filename");
process.exit(1);
}
if(!fs.existsSync(filename)) {
if (!fs.existsSync(filename)) {
console.error(n + ": " + filename + ": No such file or directory");
process.exit(2);
}
@ -209,15 +211,15 @@ wb_formats_2.forEach(function(m) { if(program[m[0]] || isfmt(m[0])) {
} });
var target_sheet = sheetname || '';
if(target_sheet === '') {
if(+program.sheetIndex < (wb.SheetNames||[]).length) target_sheet = wb.SheetNames[+program.sheetIndex];
else target_sheet = (wb.SheetNames||[""])[0];
if (target_sheet === '') {
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) {
if (!ws) {
console.error("Sheet " + target_sheet + " cannot be found");
process.exit(3);
}
@ -226,7 +228,7 @@ try {
process.exit(4);
}
if(!program.quiet && !program.book) console.error(target_sheet);
if (!program.quiet && !program.book) console.error(target_sheet);
/* single worksheet file formats */
[
@ -254,21 +256,21 @@ if(!program.quiet && !program.book) console.error(target_sheet);
process.exit(0);
} });
function outit(o, fn) { if(fn) fs.writeFileSync(fn, o); else console.log(o); }
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"); */
/*:: 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) {
switch (true) {
case program.formulae:
doit(function(ws) { return X.utils.sheet_to_formulae(ws).join("\n"); });
doit(function (ws) { return X.utils.sheet_to_formulae(ws).join("\n"); });
break;
case program.arrays: jso.header = 1;
@ -276,33 +278,33 @@ switch(true) {
case program.rawJs: jso.raw = true;
/* falls through */
case program.json:
doit(function(ws) { return JSON.stringify(X.utils.sheet_to_json(ws,jso)); });
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));
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}); });
} 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));
if (Object.assign && Object.entries) propaoa = Object.entries(Object.assign({}, wb.Props, wb.Custprops));
else {
var Keys/*:: :Array<string> = []*/, pi;
if(wb.Props) {
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]]]);
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) {
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]]]);
for (pi = 0; pi < Keys.length; ++pi) {
if (Object.prototype.hasOwnProperty.call(Keys, Keys[pi])) propaoa.push([Keys[pi], Keys[/*::+*/Keys[pi]]]);
}
}
}

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

@ -1 +1 @@
XLSX.version = '0.18.10';
XLSX.version = '0.20.3';

@ -6,26 +6,26 @@ 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 */
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; };
@ -41,6 +41,11 @@ function utf16leread(data/*:string*/)/*:string*/ {
for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data.charCodeAt(2*i) + (data.charCodeAt(2*i+1)<<8));
return o.join("");
}
function utf16lereadu(data/*:Uint8Array*/)/*:string*/ {
var o/*:Array<string>*/ = [];
for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data[2*i] + (data[2*i+1]<<8));
return o.join("");
}
function utf16beread(data/*:string*/)/*:string*/ {
var o/*:Array<string>*/ = [];
for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data.charCodeAt(2*i+1) + (data.charCodeAt(2*i)<<8));

@ -45,10 +45,35 @@ function Base64_encode_pass(input) {
}
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;
input = input.replace(/^data:([^\/]+\/[^\/]+)?;base64\,/, "").replace(/[^\w\+\/\=]/g, "");
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++));

@ -71,7 +71,7 @@ var bconcat = has_buf ? function(bufs) { return Buffer.concat(bufs.map(function(
for(i = 0, maxlen = 0; i < bufs.length; maxlen += len, ++i) {
len = bufs[i].length;
if(bufs[i] instanceof Uint8Array) o.set(bufs[i], maxlen);
else if(typeof bufs[i] == "string") { throw "wtf"; }
else if(typeof bufs[i] == "string") o.set(new Uint8Array(s2a(bufs[i])), maxlen);
else o.set(new Uint8Array(bufs[i]), maxlen);
}
return o;

@ -173,8 +173,20 @@ function SSF_frac(x/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Array<number
var q = Math.floor(sgn * P/Q);
return [q, sgn*P - q*Q, Q];
}
function SSF_normalize_xl_unsafe(v/*:number*/)/*:number*/ {
var s = v.toPrecision(16);
if(s.indexOf("e") > -1) {
var m = s.slice(0, s.indexOf("e"));
m = m.indexOf(".") > -1 ? m.slice(0, (m.slice(0,2) == "0." ? 17 : 16)) : (m.slice(0,15) + fill("0", m.length - 15));
return m + s.slice(s.indexOf("e"));
}
var n = s.indexOf(".") > -1 ? s.slice(0, (s.slice(0,2) == "0." ? 17 : 16)) : (s.slice(0,15) + fill("0", s.length - 15));
return Number(n);
}
function SSF_parse_date_code(v/*:number*/,opts/*:?any*/,b2/*:?boolean*/) {
if(v > 2958465 || v < 0) return null;
v = SSF_normalize_xl_unsafe(v);
var date = (v|0), time = Math.floor(86400 * (v - date)), dow=0;
var dout=[];
var out={D:date, T:time, u:86400*(v-date)-time,y:0,m:0,d:0,H:0,M:0,S:0,q:0};
@ -203,15 +215,6 @@ function SSF_parse_date_code(v/*:number*/,opts/*:?any*/,b2/*:?boolean*/) {
out.q = dow;
return out;
}
var SSFbasedate = /*#__PURE__*/new Date(1899, 11, 31, 0, 0, 0);
var SSFdnthresh = /*#__PURE__*/SSFbasedate.getTime();
var SSFbase1904 = /*#__PURE__*/new Date(1900, 2, 1, 0, 0, 0);
function datenum_local(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
var epoch = /*#__PURE__*/v.getTime();
if(date1904) epoch -= 1461*24*60*60*1000;
else if(v >= SSFbase1904) epoch += 24*60*60*1000;
return (epoch - (SSFdnthresh + (/*#__PURE__*/v.getTimezoneOffset() - /*#__PURE__*/SSFbasedate.getTimezoneOffset()) * 60000)) / (24 * 60 * 60 * 1000);
}
/* ECMA-376 18.8.30 numFmt*/
/* Note: `toPrecision` uses standard form when prec > E and E >= -6 */
/* exponent >= -9 and <= 9 */
@ -240,6 +243,7 @@ function SSF_large_exp(v/*:number*/)/*:string*/ {
}
function SSF_general_num(v/*:number*/)/*:string*/ {
if(!isFinite(v)) return isNaN(v) ? "#NUM!" : "#DIV/0!";
var V = Math.floor(Math.log(Math.abs(v))*Math.LOG10E), o;
if(V >= -4 && V <= -1) o = v.toPrecision(10+V);
@ -269,7 +273,7 @@ function SSF_general(v/*:any*/, opts/*:any*/) {
case 'undefined': return "";
case 'object':
if(v == null) return "";
if(v instanceof Date) return SSF_format(14, datenum_local(v, opts && opts.date1904), opts);
if(v instanceof Date) return SSF_format(14, datenum(v, opts && opts.date1904), opts);
}
throw new Error("unsupported value in General format: " + v);
}
@ -337,7 +341,7 @@ function SSF_write_date(type/*:number*/, fmt/*:string*/, val, ss0/*:?number*/)/*
switch(fmt) {
case '[h]': case '[hh]': out = val.D*24+val.H; break;
case '[m]': case '[mm]': out = (val.D*24+val.H)*60+val.M; break;
case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+Math.round(val.S+val.u); break;
case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+(ss0 == 0 ? Math.round(val.S+val.u) : val.S); break;
default: throw 'bad abstime format: ' + fmt;
} outl = fmt.length === 3 ? 1 : 2; break;
case 101: /* 'e' era */
@ -405,7 +409,7 @@ function write_num_f2(r/*:Array<string>*/, aval/*:number*/, sign/*:string*/)/*:s
return sign + (aval === 0 ? "" : ""+aval) + fill(" ", r[1].length + 2 + r[4].length);
}
var dec1 = /^#*0*\.([0#]+)/;
var closeparen = /\).*[0#]/;
var closeparen = /\)[^)]*[0#]/;
var phone = /\(###\) ###\\?-####/;
function hashq(str/*:string*/)/*:string*/ {
var o = "", cc;
@ -417,7 +421,11 @@ function hashq(str/*:string*/)/*:string*/ {
}
return o;
}
function rnd(val/*:number*/, d/*:number*/)/*:string*/ { var dd = Math.pow(10,d); return ""+(Math.round(val * dd)/dd); }
function rnd(val/*:number*/, d/*:number*/)/*:string*/ {
var sgn = val < 0 ? -1 : 1;
var dd = Math.pow(10,d);
return ""+sgn*(Math.round(sgn * val * dd)/dd);
}
function dec(val/*:number*/, d/*:number*/)/*:number*/ {
var _frac = val - Math.floor(val), dd = Math.pow(10,d);
if (d < ('' + Math.round(_frac * dd)).length) return 0;
@ -785,10 +793,11 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
switch(out[i].t) {
case 'h': case 'H': out[i].t = hr; lst='h'; if(bt < 1) bt = 1; break;
case 's':
if((ssm=out[i].v.match(/\.0+$/))) ss0=Math.max(ss0,ssm[0].length-1);
if((ssm=out[i].v.match(/\.0+$/))) { ss0=Math.max(ss0,ssm[0].length-1); bt = 4;}
if(bt < 3) bt = 3;
/* falls through */
case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break;
case 'd': case 'y': case 'e': lst=out[i].t; break;
case 'M': lst=out[i].t; if(bt < 2) bt = 2; break;
case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break;
case 'X': /*if(out[i].v === "B2");*/
break;
@ -798,19 +807,29 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
if(bt < 3 && out[i].v.match(/[Ss]/)) bt = 3;
}
}
/* time rounding depends on presence of minute / second / usec fields */
var _dt;
switch(bt) {
case 0: break;
case 1:
/*::if(!dt) break;*/
case 2:
case 3:
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
if(dt.S >= 60) { dt.S = 0; ++dt.M; }
if(dt.M >= 60) { dt.M = 0; ++dt.H; }
if(dt.H >= 24) { dt.H = 0; ++dt.D; _dt = SSF_parse_date_code(dt.D); _dt.u = dt.u; _dt.S = dt.S; _dt.M = dt.M; _dt.H = dt.H; dt = _dt; }
break;
case 2:
/*::if(!dt) break;*/
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
case 4:
switch(ss0) {
case 1: dt.u = Math.round(dt.u * 10)/10; break;
case 2: dt.u = Math.round(dt.u * 100)/100; break;
case 3: dt.u = Math.round(dt.u * 1000)/1000; break;
}
if(dt.u >= 1) { dt.u = 0; ++dt.S; }
if(dt.S >= 60) { dt.S = 0; ++dt.M; }
if(dt.M >= 60) { dt.M = 0; ++dt.H; }
if(dt.H >= 24) { dt.H = 0; ++dt.D; _dt = SSF_parse_date_code(dt.D); _dt.u = dt.u; _dt.S = dt.S; _dt.M = dt.M; _dt.H = dt.H; dt = _dt; }
break;
}
@ -926,6 +945,8 @@ function choose_fmt(f/*:string*/, v/*:any*/) {
if(l<4 && lat>-1) --l;
if(fmt.length > 4) throw new Error("cannot find right format for |" + fmt.join("|") + "|");
if(typeof v !== "number") return [4, fmt.length === 4 || lat>-1?fmt[fmt.length-1]:"@"];
/* NOTE: most spreadsheet software do not support NaN or infinities */
if(typeof v === "number" && !isFinite(v)) v = 0;
switch(fmt.length) {
case 1: fmt = lat>-1 ? ["General", "General", "General", fmt[0]] : [fmt[0], fmt[0], fmt[0], "@"]; break;
case 2: fmt = lat>-1 ? [fmt[0], fmt[0], fmt[0], fmt[1]] : [fmt[0], fmt[1], fmt[0], "@"]; break;
@ -957,11 +978,13 @@ function SSF_format(fmt/*:string|number*/,v/*:any*/,o/*:?any*/) {
break;
}
if(SSF_isgeneral(sfmt,0)) return SSF_general(v, o);
if(v instanceof Date) v = datenum_local(v, o.date1904);
if(v instanceof Date) v = datenum(v, o.date1904);
var f = choose_fmt(sfmt, v);
if(SSF_isgeneral(f[1])) return SSF_general(v, o);
if(v === true) v = "TRUE"; else if(v === false) v = "FALSE";
else if(v === "" || v == null) return "";
else if(isNaN(v) && f[1].indexOf("0") > -1) return "#NUM!";
else if(!isFinite(v) && f[1].indexOf("0") > -1) return "#DIV/0!";
return eval_fmt(f[1], v, o, f[0]);
}
function SSF_load(fmt/*:string*/, idx/*:?number*/)/*:number*/ {

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

@ -42,7 +42,9 @@ type CFBFiles = {[n:string]:CFBEntry};
var CRC32 = /*#__PURE__*/(function() {
var CRC32 = {};
CRC32.version = '1.2.0';
/* see perf/crc32table.js */
/*::
type CRC32TableType = Array<number> | Int32Array;
*/
/*global Int32Array */
function signed_crc_table()/*:any*/ {
var c = 0, table/*:Array<number>*/ = new Array(256);
@ -73,14 +75,14 @@ function slice_by_16_tables(T) {
for(c = 256 + n; c < 4096; c += 256) v = table[c] = (v >>> 8) ^ T[v & 0xFF];
}
var out = [];
for(n = 1; n != 16; ++n) out[n - 1] = typeof Int32Array !== 'undefined' ? table.subarray(n * 256, n * 256 + 256) : table.slice(n * 256, n * 256 + 256);
for(n = 1; n != 16; ++n) out[n - 1] = typeof Int32Array !== 'undefined' && typeof table.subarray == "function" ? table.subarray(n * 256, n * 256 + 256) : table.slice(n * 256, n * 256 + 256);
return out;
}
var TT = slice_by_16_tables(T0);
var T1 = TT[0], T2 = TT[1], T3 = TT[2], T4 = TT[3], T5 = TT[4];
var T6 = TT[5], T7 = TT[6], T8 = TT[7], T9 = TT[8], Ta = TT[9];
var Tb = TT[10], Tc = TT[11], Td = TT[12], Te = TT[13], Tf = TT[14];
function crc32_bstr(bstr/*:string*/, seed/*:number*/)/*:number*/ {
function crc32_bstr(bstr/*:string*/, seed/*:?number*/)/*:number*/ {
var C = seed/*:: ? 0 : 0 */ ^ -1;
for(var i = 0, L = bstr.length; i < L;) C = (C>>>8) ^ T0[(C^bstr.charCodeAt(i++))&0xFF];
return ~C;
@ -306,7 +308,7 @@ sleuth_fat(difat_start, difat_sec_cnt, sectors, ssz, fat_addrs);
/** Chains */
var sector_list/*:SectorList*/ = make_sector_list(sectors, dir_start, fat_addrs, ssz);
sector_list[dir_start].name = "!Directory";
if(dir_start < sector_list.length) sector_list[dir_start].name = "!Directory";
if(nmfs > 0 && minifat_start !== ENDOFCHAIN) sector_list[minifat_start].name = "!MiniFAT";
sector_list[fat_addrs[0]].name = "!FAT";
sector_list.fat_addrs = fat_addrs;
@ -769,9 +771,9 @@ function _write(cfb/*:CFBContainer*/, options/*:CFBWriteOpts*/)/*:RawBytes|strin
file = cfb.FileIndex[i];
if(i === 0) file.start = file.size ? file.start - 1 : ENDOFCHAIN;
var _nm/*:string*/ = (i === 0 && _opts.root) || file.name;
if(_nm.length > 32) {
console.error("Name " + _nm + " will be truncated to " + _nm.slice(0,32));
_nm = _nm.slice(0, 32);
if(_nm.length > 31) {
console.error("Name " + _nm + " will be truncated to " + _nm.slice(0,31));
_nm = _nm.slice(0, 31);
}
flen = 2*(_nm.length+1);
o.write_shift(64, _nm, "utf16le");
@ -1446,8 +1448,8 @@ function parse_local_file(blob/*:CFBlob*/, csz/*:number*/, usz/*:number*/, o/*:C
if((ef[0x0001]||{}).csz) _csz = ef[0x0001].csz;
if(EF) {
if((EF[0x5455]||{}).mt) date = EF[0x5455].mt;
if((EF[0x0001]||{}).usz) _usz = ef[0x0001].usz;
if((EF[0x0001]||{}).csz) _csz = ef[0x0001].csz;
if((EF[0x0001]||{}).usz) _usz = EF[0x0001].usz;
if((EF[0x0001]||{}).csz) _csz = EF[0x0001].csz;
}
}
blob.l += efsz;
@ -1458,7 +1460,7 @@ function parse_local_file(blob/*:CFBlob*/, csz/*:number*/, usz/*:number*/, o/*:C
var data = blob.slice(blob.l, blob.l + _csz);
switch(meth) {
case 8: data = _inflateRawSync(blob, _usz); break;
case 0: break; // TODO: scan for magic number
case 0: blob.l += _csz; break; // TODO: scan for magic number
default: throw new Error("Unsupported ZIP Compression method " + meth);
}
@ -1493,16 +1495,17 @@ function write_zip(cfb/*:CFBContainer*/, options/*:CFBWriteOpts*/)/*:RawBytes*/
for(i = 1; i < cfb.FullPaths.length; ++i) {
fp = cfb.FullPaths[i].slice(root.length); fi = cfb.FileIndex[i];
if(!fi.size || !fi.content || fp == "\u0001Sh33tJ5") continue;
if(!fi.size || !fi.content || (Array.isArray(fi.content) && fi.content.length == 0) || fp == "\u0001Sh33tJ5") continue;
var start = start_cd;
/* TODO: CP437 filename */
var namebuf = new_buf(fp.length);
for(j = 0; j < fp.length; ++j) namebuf.write_shift(1, fp.charCodeAt(j) & 0x7F);
namebuf = namebuf.slice(0, namebuf.l);
crcs[fcnt] = CRC32.buf(/*::((*/fi.content/*::||[]):any)*/, 0);
crcs[fcnt] = typeof fi.content == "string" ? CRC32.bstr(fi.content, 0) : CRC32.buf(/*::((*/fi.content/*::||[]):any)*/, 0);
var outbuf = fi.content/*::||[]*/;
var outbuf = typeof fi.content == "string" ? s2a(fi.content) : fi.content/*::||[]*/;
if(method == 8) outbuf = _deflateRawSync(outbuf);
/* local file header */
@ -1683,7 +1686,7 @@ function parse_mime(cfb/*:CFBContainer*/, data/*:Array<string>*/, root/*:string*
for(;di < 10; ++di) {
var line = data[di];
if(!line || line.match(/^\s*$/)) break;
var m = line.match(/^(.*?):\s*([^\s].*)$/);
var m = line.match(/^([^:]*?):\s*([^\s].*)$/);
if(m) switch(m[1].toLowerCase()) {
case "content-location": fname = m[2].trim(); break;
case "content-type": ctype = m[2].trim(); break;

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

@ -31,22 +31,19 @@ function evert_arr(obj/*:any*/)/*:EvertArrType*/ {
return o;
}
var basedate = /*#__PURE__*/new Date(1899, 11, 30, 0, 0, 0); // 2209161600000
var dnthresh = /*#__PURE__*/Date.UTC(1899, 11, 30, 0, 0, 0); // -2209161600000
var dnthresh1 = /*#__PURE__*/Date.UTC(1899, 11, 31, 0, 0, 0); // -2209075200000
var dnthresh2 = /*#__PURE__*/Date.UTC(1904, 0, 1, 0, 0, 0); // -2209075200000
function datenum(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
var epoch = /*#__PURE__*/v.getTime();
if(date1904) epoch -= 1462*24*60*60*1000;
var dnthresh = /*#__PURE__*/basedate.getTime() + (/*#__PURE__*/v.getTimezoneOffset() - /*#__PURE__*/basedate.getTimezoneOffset()) * 60000;
return (epoch - dnthresh) / (24 * 60 * 60 * 1000);
var res = (epoch - dnthresh) / (24 * 60 * 60 * 1000);
if(date1904) { res -= 1462; return res < -1402 ? res - 1 : res; }
return res < 60 ? res - 1 : res;
}
var refdate = /*#__PURE__*/new Date();
var dnthresh = /*#__PURE__*/basedate.getTime() + (/*#__PURE__*/refdate.getTimezoneOffset() - /*#__PURE__*/basedate.getTimezoneOffset()) * 60000;
var refoffset = /*#__PURE__*/refdate.getTimezoneOffset();
function numdate(v/*:number*/)/*:Date*/ {
function numdate(v/*:number*/)/*:Date|number*/ {
if(v >= 60 && v < 61) return v;
var out = new Date();
out.setTime(v * 24 * 60 * 60 * 1000 + dnthresh);
if (out.getTimezoneOffset() !== refoffset) {
out.setTime(out.getTime() + (out.getTimezoneOffset() - refoffset) * 60000);
}
out.setTime((v>60 ? v : (v+1)) * 24 * 60 * 60 * 1000 + dnthresh);
return out;
}
@ -77,28 +74,22 @@ function parse_isodur(s) {
return sec;
}
var good_pd_date_1 = /*#__PURE__*/new Date('2017-02-19T19:06:09.000Z');
var good_pd_date = /*#__PURE__*/isNaN(/*#__PURE__*/good_pd_date_1.getFullYear()) ? /*#__PURE__*/new Date('2/19/17') : good_pd_date_1;
var good_pd = /*#__PURE__*/good_pd_date.getFullYear() == 2017;
/* parses a date as a local date */
function parseDate(str/*:string|Date*/, fixdate/*:?number*/)/*:Date*/ {
var d = new Date(str);
if(good_pd) {
/*:: if(fixdate == null) fixdate = 0; */
if(fixdate > 0) d.setTime(d.getTime() + d.getTimezoneOffset() * 60 * 1000);
else if(fixdate < 0) d.setTime(d.getTime() - d.getTimezoneOffset() * 60 * 1000);
return d;
}
/* Blame https://bugs.chromium.org/p/v8/issues/detail?id=7863 for the regexide */
var pdre1 = /^(\d+):(\d+)(:\d+)?(\.\d+)?$/; // HH:MM[:SS[.UUU]]
var pdre2 = /^(\d+)-(\d+)-(\d+)$/; // YYYY-mm-dd
var pdre3 = /^(\d+)-(\d+)-(\d+)[T ](\d+):(\d+)(:\d+)?(\.\d+)?$/; // YYYY-mm-dd(T or space)HH:MM[:SS[.UUU]], sans "Z"
/* parses a date string as a UTC date */
function parseDate(str/*:string*/, date1904/*:boolean*/)/*:Date*/ {
if(str instanceof Date) return str;
if(good_pd_date.getFullYear() == 1917 && !isNaN(d.getFullYear())) {
var s = d.getFullYear();
if(str.indexOf("" + s) > -1) return d;
d.setFullYear(d.getFullYear() + 100); return d;
}
var n = str.match(/\d+/g)||["2017","2","19","0","0","0"];
var out = new Date(+n[0], +n[1] - 1, +n[2], (+n[3]||0), (+n[4]||0), (+n[5]||0));
if(str.indexOf("Z") > -1) out = new Date(out.getTime() - out.getTimezoneOffset() * 60 * 1000);
return out;
var m = str.match(pdre1);
if(m) return new Date((date1904 ? dnthresh2 : dnthresh1) + ((parseInt(m[1], 10)*60 + parseInt(m[2], 10))*60 + (m[3] ? parseInt(m[3].slice(1), 10) : 0))*1000 + (m[4] ? parseInt((m[4]+"000").slice(1,4), 10) : 0));
m = str.match(pdre2);
if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], 0, 0, 0, 0));
/* TODO: 1900-02-29T00:00:00.000 should return a flag to treat as a date code (affects xlml) */
m = str.match(pdre3);
if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], +m[4], +m[5], ((m[6] && parseInt(m[6].slice(1), 10))|| 0), ((m[7] && parseInt((m[7] + "0000").slice(1,4), 10))||0)));
var d = new Date(str);
return d;
}
function cc2str(arr/*:Array<number>*/, debomit)/*:string*/ {
@ -129,8 +120,18 @@ function cc2str(arr/*:Array<number>*/, debomit)/*:string*/ {
return new TextDecoder("latin1").decode(arr).replace(/[€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ]/g, function(c) { return rev[c] || c; });
} catch(e) {}
var o = [];
for(var i = 0; i != arr.length; ++i) o.push(String.fromCharCode(arr[i]));
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("");
}
@ -153,39 +154,56 @@ function fuzzynum(s/*:string*/)/*:number*/ {
var wt = 1;
var ss = s.replace(/([\d]),([\d])/g,"$1$2").replace(/[$]/g,"").replace(/[%]/g, function() { wt *= 100; return "";});
if(!isNaN(v = Number(ss))) return v / wt;
ss = ss.replace(/[(](.*)[)]/,function($$, $1) { wt = -wt; return $1;});
ss = ss.replace(/[(]([^()]*)[)]/,function($$, $1) { wt = -wt; return $1;});
if(!isNaN(v = Number(ss))) return v / wt;
return v;
}
/* NOTE: Chrome rejects bare times like 1:23 PM */
var FDRE1 = /^(0?\d|1[0-2])(?:|:([0-5]?\d)(?:|(\.\d+)(?:|:([0-5]?\d))|:([0-5]?\d)(|\.\d+)))\s+([ap])m?$/;
var FDRE2 = /^([01]?\d|2[0-3])(?:|:([0-5]?\d)(?:|(\.\d+)(?:|:([0-5]?\d))|:([0-5]?\d)(|\.\d+)))$/;
var FDISO = /^(\d+)-(\d+)-(\d+)[T ](\d+):(\d+)(:\d+)(\.\d+)?[Z]?$/; // YYYY-mm-dd(T or space)HH:MM:SS[.UUU][Z]
/* TODO: 1904 adjustment */
var utc_append_works = new Date("6/9/69 00:00 UTC").valueOf() == -17798400000;
function fuzzytime1(M) /*:Date*/ {
/* TODO: 1904 adjustment, keep in sync with base date */
if(!M[2]) return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), 0, 0, 0);
if(M[3]) {
if(M[4]) return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[4], parseFloat(M[3])*1000);
else return new Date(1899,11,30,(M[7] == "p" ? 12 : 0), +M[1], +M[2], parseFloat(M[3])*1000);
}
else if(M[5]) return new Date(1899,11,30, (+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[5], M[6] ? parseFloat(M[6]) * 1000 : 0);
else return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], 0, 0);
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);
var o = new Date(s), n = new Date(NaN);
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;
if(y < 0 || y > 8099 || s.match(/[^-0-9:,\/\\\ ]/)) return n;
return o;
}
@ -198,3 +216,165 @@ var split_regex = /*#__PURE__*/(function() {
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;
};
})();

@ -67,6 +67,9 @@ function zipentries(zip) {
function zip_add_file(zip, path, content) {
if(zip.FullPaths) {
if(Array.isArray(content) && typeof content[0] == "string") {
content = content.join("");
}
if(typeof content == "string") {
var res;
if(has_buf) res = Buffer_from(content);

@ -1,6 +1,6 @@
var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n';
var attregexg=/([^"\s?>\/]+)\s*=\s*((?:")([^"]*)(?:")|(?:')([^']*)(?:')|([^'">\s]+))/g;
var tagregex1=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'">\s=]+))*\s*[\/\?]?>/mg, tagregex2 = /<[^>]*>/g;
var attregexg=/\s([^"\s?>\/]+)\s*=\s*((?:")([^"]*)(?:")|(?:')([^']*)(?:')|([^'">\s]+))/g;
var tagregex1=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?<>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'"<>\s=]+))*\s*[\/\?]?>/mg, tagregex2 = /<[^<>]*>/g;
var tagregex = /*#__PURE__*/XML_HEADER.match(tagregex1) ? tagregex1 : tagregex2;
var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
function parsexmltag(tag/*:string*/, skip_root/*:?boolean*/, skip_LC/*:?boolean*/)/*:any*/ {
@ -11,7 +11,7 @@ function parsexmltag(tag/*:string*/, skip_root/*:?boolean*/, skip_LC/*:?boolean*
if(eq === tag.length) return z;
var m = tag.match(attregexg), j=0, v="", i=0, q="", cc="", quot = 1;
if(m) for(i = 0; i != m.length; ++i) {
cc = m[i];
cc = m[i].slice(1);
for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break;
q = cc.slice(0,c).trim();
while(cc.charCodeAt(c+1) == 32) ++c;
@ -32,6 +32,26 @@ function parsexmltag(tag/*:string*/, skip_root/*:?boolean*/, skip_LC/*:?boolean*
}
return z;
}
function parsexmltagraw(tag/*:string*/, skip_root/*:?boolean*/, skip_LC/*:?boolean*/)/*:any*/ {
var z = ({}/*:any*/);
var eq = 0, c = 0;
for(; eq !== tag.length; ++eq) if((c = tag.charCodeAt(eq)) === 32 || c === 10 || c === 13) break;
if(!skip_root) z[0] = tag.slice(0, eq);
if(eq === tag.length) return z;
var m = tag.match(attregexg), j=0, v="", i=0, q="", cc="", quot = 1;
if(m) for(i = 0; i != m.length; ++i) {
cc = m[i].slice(1);
for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break;
q = cc.slice(0,c).trim();
while(cc.charCodeAt(c+1) == 32) ++c;
quot = ((eq=cc.charCodeAt(c+1)) == 34 || eq == 39) ? 1 : 0;
v = cc.slice(c+1+quot, cc.length-quot);
if(q.indexOf("_") > 0) q = q.slice(0, q.indexOf("_")); // from ods
z[q] = v;
if(!skip_LC) z[q.toLowerCase()] = v;
}
return z;
}
function strip_ns(x/*:string*/)/*:string*/ { return x.replace(nsregex2, "<$1"); }
var encodings = {
@ -47,7 +67,7 @@ var rencoding = /*#__PURE__*/evert(encodings);
// TODO: CP remap (need to read file version to determine OS)
var unescapexml/*:StringConv*/ = /*#__PURE__*/(function() {
/* 22.4.2.4 bstr (Basic String) */
var encregex = /&(?:quot|apos|gt|lt|amp|#x?([\da-fA-F]+));/ig, coderegex = /_x([\da-fA-F]{4})_/ig;
var encregex = /&(?:quot|apos|gt|lt|amp|#x?([\da-fA-F]+));/ig, coderegex = /_x([\da-fA-F]{4})_/g;
function raw_unescapexml(text/*:string*/)/*:string*/ {
var s = text + '', i = s.indexOf("<![CDATA[");
if(i == -1) return s.replace(encregex, function($$, $1) { return encodings[$$]||String.fromCharCode(parseInt($1,$$.indexOf("x")>-1?16:10))||$$; }).replace(coderegex,function(m,c) {return String.fromCharCode(parseInt(c,16));});
@ -133,7 +153,13 @@ function utf8readb(data) {
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 utf8read = /*#__PURE__*/(function() {
if(has_buf) {
if(utf8readc(utf8corpus) == utf8reada(utf8corpus)) return utf8readc;
if(utf8readb(utf8corpus) == utf8reada(utf8corpus)) return utf8readb;
}
return 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;
@ -161,16 +187,6 @@ var utf8write/*:StringConv*/ = has_buf ? function(data) { return Buffer_from(dat
return out.join("");
};
// matches <foo>...</foo> extracts content
var matchtag = /*#__PURE__*/(function() {
var mtcache/*:{[k:string]:RegExp}*/ = ({}/*:any*/);
return function matchtag(f/*:string*/,g/*:?string*/)/*:RegExp*/ {
var t = f+"|"+(g||"");
if(mtcache[t]) return mtcache[t];
return (mtcache[t] = new RegExp('<(?:\\w+:)?'+f+'(?: xml:space="preserve")?(?:[^>]*)>([\\s\\S]*?)</(?:\\w+:)?'+f+'>',((g||"")/*:any*/)));
};
})();
var htmldecode/*:{(s:string):string}*/ = /*#__PURE__*/(function() {
var entities/*:Array<[RegExp, string]>*/ = [
['nbsp', ' '], ['middot', '·'],
@ -181,30 +197,25 @@ var htmldecode/*:{(s:string):string}*/ = /*#__PURE__*/(function() {
// Remove new lines and spaces from start of content
.replace(/^[\t\n\r ]+/, "")
// Remove new lines and spaces from end of content
.replace(/[\t\n\r ]+$/,"")
.replace(/(^|[^\t\n\r ])[\t\n\r ]+$/,"$1")
// Added line which removes any white space characters after and before html tags
.replace(/>\s+/g,">").replace(/\s+</g,"<")
.replace(/>\s+/g,">").replace(/\b\s+</g,"<")
// Replace remaining new lines and spaces with space
.replace(/[\t\n\r ]+/g, " ")
// Replace <br> tags with new lines
.replace(/<\s*[bB][rR]\s*\/?>/g,"\n")
// Strip HTML elements
.replace(/<[^>]*>/g,"");
.replace(/<[^<>]*>/g,"");
for(var i = 0; i < entities.length; ++i) o = o.replace(entities[i][0], entities[i][1]);
return o;
};
})();
var vtregex = /*#__PURE__*/(function(){ var vt_cache = {};
return function vt_regex(bt) {
if(vt_cache[bt] !== undefined) return vt_cache[bt];
return (vt_cache[bt] = new RegExp("<(?:vt:)?" + bt + ">([\\s\\S]*?)</(?:vt:)?" + bt + ">", 'g') );
};})();
var vtvregex = /<\/?(?:vt:)?variant>/g, vtmregex = /<(?:vt:)([^>]*)>([\s\S]*)</;
var vtvregex = /<\/?(?:vt:)?variant>/g, vtmregex = /<(?:vt:)([^<"'>]*)>([\s\S]*)</;
function parseVector(data/*:string*/, opts)/*:Array<{v:string,t:string}>*/ {
var h = parsexmltag(data);
var matches/*:Array<string>*/ = data.match(vtregex(h.baseType))||[];
var matches/*:Array<string>*/ = str_match_xml_ns_g(data, h.baseType)||[];
var res/*:Array<any>*/ = [];
if(matches.length != h.size) {
if(opts.WTF) throw new Error("unexpected vector length " + matches.length + " != " + h.size);
@ -245,9 +256,8 @@ function xlml_normalize(d)/*:string*/ {
if(typeof Uint8Array !== 'undefined' && d instanceof Uint8Array) return utf8read(a2s(ab2a(d)));
throw new Error("Bad input format: expected Buffer or string");
}
/* UOS uses CJK in tags */
var xlmlregex = /<(\/?)([^\s?><!\/:]*:|)([^\s?<>:\/]+)(?:[\s?:\/](?:[^>=]|="[^"]*?")*)?>/mg;
//var xlmlregex = /<(\/?)([a-z0-9]*:|)(\w+)[^>]*>/mg;
/* 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',

@ -181,21 +181,29 @@ function WriteShift(t/*:number*/, val/*:string|number*/, f/*:?string*/)/*:any*/
/*:: if(typeof val !== 'string') throw new Error("unreachable"); */
for(i = 0; i != val.length; ++i) __writeUInt16LE(this, val.charCodeAt(i), this.l + 2 * i);
size = 2 * val.length;
} else if(f === 'sbcs') {
} else if(f === 'sbcs' || f == 'cpstr') {
if(typeof $cptable !== 'undefined' && current_ansi == 874) {
/* TODO: use tables directly, don't encode */
/*:: if(typeof val !== "string") throw new Error("unreachable"); */
for(i = 0; i != val.length; ++i) {
var cppayload = $cptable.utils.encode(current_ansi, val.charAt(i));
this[this.l + i] = cppayload[0];
var cpp = $cptable.utils.encode(current_ansi, val.charAt(i));
this[this.l + i] = cpp[0];
}
size = val.length;
} else if(typeof $cptable !== 'undefined' && f == 'cpstr') {
cpp = $cptable.utils.encode(current_codepage, val);
/* replace null bytes with _ when relevant */
if(cpp.length == val.length) for(i = 0; i < val.length; ++i) if(cpp[i] == 0 && val.charCodeAt(i) != 0) cpp[i] = 0x5F;
if(cpp.length == 2 * val.length) for(i = 0; i < val.length; ++i) if(cpp[2*i] == 0 && cpp[2*i+1] == 0 && val.charCodeAt(i) != 0) cpp[2*i] = 0x5F;
for(i = 0; i < cpp.length; ++i) this[this.l + i] = cpp[i];
size = cpp.length;
} else {
/*:: if(typeof val !== 'string') throw new Error("unreachable"); */
val = val.replace(/[^\x00-\x7F]/g, "_");
/*:: if(typeof val !== 'string') throw new Error("unreachable"); */
for(i = 0; i != val.length; ++i) this[this.l + i] = (val.charCodeAt(i) & 0xFF);
size = val.length;
}
size = val.length;
} else if(f === 'hex') {
for(; i < t; ++i) {
/*:: if(typeof val !== "string") throw new Error("unreachable"); */

@ -20,7 +20,9 @@ function recordhopper(data, cb/*:RecordHopperCB*/, opts/*:?any*/) {
/* control buffer usage for fixed-length buffers */
function buf_array()/*:BufArray*/ {
var bufs/*:Array<Block>*/ = [], blksz = has_buf ? 256 : 2048;
var bufs/*:Array<Block>*/ = [], blksz = has_buf ? 16384 : 2048;
var has_buf_subarray = has_buf && (typeof new_buf(blksz).subarray == "function");
var newblk = function ba_newblk(sz/*:number*/)/*:Block*/ {
var o/*:Block*/ = (new_buf(sz)/*:any*/);
prep_blob(o, 0);
@ -49,10 +51,18 @@ function buf_array()/*:BufArray*/ {
endbuf();
return bconcat(bufs);
};
var end2 = function() {
endbuf(); return bufs;
};
var push = function ba_push(buf) { endbuf(); curbuf = buf; if(curbuf.l == null) curbuf.l = curbuf.length; next(blksz); };
var push = function ba_push(buf) {
if(curbuf.l > 0) bufs.push(curbuf.slice(0, curbuf.l));
bufs.push(buf);
curbuf = has_buf_subarray ? curbuf.subarray(curbuf.l || 0) : curbuf.slice(curbuf.l || 0);
prep_blob(curbuf, 0);
};
return ({ next:next, push:push, end:end, _bufs:bufs }/*:any*/);
return ({ next:next, push:push, end:end, _bufs:bufs, end2:end2 }/*:any*/);
}
function write_record(ba/*:BufArray*/, type/*:number*/, payload, length/*:?number*/) {

@ -9,7 +9,6 @@ function fix_col(cstr/*:string*/)/*:string*/ { return cstr.replace(/^([A-Z])/,"$
function unfix_col(cstr/*:string*/)/*:string*/ { return cstr.replace(/^\$([A-Z])/,"$1"); }
function split_cell(cstr/*:string*/)/*:Array<string>*/ { return cstr.replace(/(\$?[A-Z]*)(\$?\d*)/,"$1,$2").split(","); }
//function decode_cell(cstr/*:string*/)/*:CellAddress*/ { var splt = split_cell(cstr); return { c:decode_col(splt[0]), r:decode_row(splt[1]) }; }
function decode_cell(cstr/*:string*/)/*:CellAddress*/ {
var R = 0, C = 0;
for(var i = 0; i < cstr.length; ++i) {
@ -19,7 +18,6 @@ function decode_cell(cstr/*:string*/)/*:CellAddress*/ {
}
return { c: C - 1, r:R - 1 };
}
//function encode_cell(cell/*:CellAddress*/)/*:string*/ { return encode_col(cell.c) + encode_row(cell.r); }
function encode_cell(cell/*:CellAddress*/)/*:string*/ {
var col = cell.c + 1;
var s="";
@ -110,11 +108,19 @@ function sheet_to_workbook(sheet/*:Worksheet*/, opts)/*:Workbook*/ {
return { SheetNames: [n], Sheets: sheets };
}
function sheet_new(opts) {
var out = {};
var o = opts || {};
if(o.dense) out["!data"] = [];
return out;
}
function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ {
var o = opts || {};
var dense = _ws ? Array.isArray(_ws) : o.dense;
var dense = _ws ? (_ws["!data"] != null) : o.dense;
if(DENSE != null && dense == null) dense = DENSE;
var ws/*:Worksheet*/ = _ws || (dense ? ([]/*:any*/) : ({}/*:any*/));
var ws/*:Worksheet*/ = _ws || (dense ? ({"!data": []}) : ({}/*:any*/));
if(dense && !ws["!data"]) ws["!data"] = [];
var _R = 0, _C = 0;
if(ws && o.origin != null) {
if(typeof o.origin == 'number') _R = o.origin;
@ -122,59 +128,71 @@ function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksh
var _origin/*:CellAddress*/ = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin;
_R = _origin.r; _C = _origin.c;
}
if(!ws["!ref"]) ws["!ref"] = "A1:A1";
}
var range/*:Range*/ = ({s: {c:10000000, r:10000000}, e: {c:0, r:0}}/*:any*/);
if(ws['!ref']) {
if(ws["!ref"]){
var _range = safe_decode_range(ws['!ref']);
range.s.c = _range.s.c;
range.s.r = _range.s.r;
range.e.c = Math.max(range.e.c, _range.e.c);
range.e.r = Math.max(range.e.r, _range.e.r);
if(_R == -1) range.e.r = _R = _range.e.r + 1;
if(_R == -1) range.e.r = _R = (ws["!ref"] ? _range.e.r + 1 : 0);
} else {
range.s.c = range.e.c = range.s.r = range.e.r = 0;
}
var row = [], seen = false;
for(var R = 0; R != data.length; ++R) {
if(!data[R]) continue;
if(!Array.isArray(data[R])) throw new Error("aoa_to_sheet expects an array of arrays");
for(var C = 0; C != data[R].length; ++C) {
if(typeof data[R][C] === 'undefined') continue;
var cell/*:Cell*/ = ({v: data[R][C] }/*:any*/);
var __R = _R + R, __C = _C + C;
var __R = _R + R;
if(dense) {
if(!ws["!data"][__R]) ws["!data"][__R] = [];
row = ws["!data"][__R];
}
var data_R = data[R];
for(var C = 0; C != data_R.length; ++C) {
if(typeof data_R[C] === 'undefined') continue;
var cell/*:Cell*/ = ({v: data_R[C], t:"" }/*:any*/);
var __C = _C + C;
if(range.s.r > __R) range.s.r = __R;
if(range.s.c > __C) range.s.c = __C;
if(range.e.r < __R) range.e.r = __R;
if(range.e.c < __C) range.e.c = __C;
if(data[R][C] && typeof data[R][C] === 'object' && !Array.isArray(data[R][C]) && !(data[R][C] instanceof Date)) cell = data[R][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(Array.isArray(cell.v)) { cell.f = data_R[C][1]; cell.v = cell.v[0]; }
if(cell.v === null) {
if(cell.f) cell.t = 'n';
else if(o.nullError) { cell.t = 'e'; cell.v = 0; }
else if(!o.sheetStubs) continue;
else cell.t = 'z';
}
else if(typeof cell.v === 'number') cell.t = 'n';
else if(typeof cell.v === '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(!ws[__R]) ws[__R] = [];
if(ws[__R][__C] && ws[__R][__C].z) cell.z = ws[__R][__C].z;
ws[__R][__C] = cell;
if(row[__C] && row[__C].z) cell.z = row[__C].z;
row[__C] = cell;
} else {
var cell_ref = encode_cell(({c:__C,r:__R}/*:any*/));
var cell_ref = encode_col(__C) + (__R + 1)/*:any*/;
if(ws[cell_ref] && ws[cell_ref].z) cell.z = ws[cell_ref].z;
ws[cell_ref] = cell;
}
}
}
if(range.s.c < 10000000) ws['!ref'] = encode_range(range);
if(seen && range.s.c < 10400000) ws['!ref'] = encode_range(range);
return ws;
}
function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ { return sheet_add_aoa(null, data, opts); }

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

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

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

@ -18,22 +18,12 @@ var CORE_PROPS/*:Array<Array<string> >*/ = [
["dcterms:modified", "ModifiedDate", 'date']
];
var CORE_PROPS_REGEX/*:Array<RegExp>*/ = /*#__PURE__*/(function() {
var r = new Array(CORE_PROPS.length);
for(var i = 0; i < CORE_PROPS.length; ++i) {
var f = CORE_PROPS[i];
var g = "(?:"+ f[0].slice(0,f[0].indexOf(":")) +":)"+ f[0].slice(f[0].indexOf(":")+1);
r[i] = new RegExp("<" + g + "[^>]*>([\\s\\S]*?)<\/" + g + ">");
}
return r;
})();
function parse_core_props(data) {
var p = {};
data = utf8read(data);
for(var i = 0; i < CORE_PROPS.length; ++i) {
var f = CORE_PROPS[i], cur = data.match(CORE_PROPS_REGEX[i]);
var f = CORE_PROPS[i], cur = str_match_xml(data, f[0]);
if(cur != null && cur.length > 0) p[f[1]] = unescapexml(cur[1]);
if(f[2] === 'date' && p[f[1]]) p[f[1]] = parseDate(p[f[1]]);
}

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

@ -1,5 +1,5 @@
/* 15.2.12.2 Custom File Properties Part */
var custregex = /<[^>]+>[^<]*/g;
var custregex = /<[^<>]+>[^<]*/g;
function parse_cust_props(data/*:string*/, opts) {
var p = {}, name = "";
var m = data.match(custregex);

@ -123,8 +123,8 @@ function parse_TypedPropertyValue(blob, type/*:number*/, _opts)/*:any*/ {
case 0x03 /*VT_I4*/: ret = blob.read_shift(4, 'i'); return ret;
case 0x0B /*VT_BOOL*/: return blob.read_shift(4) !== 0x0;
case 0x13 /*VT_UI4*/: ret = blob.read_shift(4); return ret;
case 0x1E /*VT_LPSTR*/: return parse_lpstr(blob, t, 4).replace(chr0,'');
case 0x1F /*VT_LPWSTR*/: return parse_lpwstr(blob);
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 0x40 /*VT_FILETIME*/: return parse_FILETIME(blob);
case 0x41 /*VT_BLOB*/: return parse_BLOB(blob);
case 0x47 /*VT_CF*/: return parse_ClipboardData(blob);
@ -233,8 +233,8 @@ function parse_PropertySet(blob, PIDSI) {
/* [MS-OSHARED] 2.3.3.2.3.1.2 + PROPVARIANT */
switch(blob[blob.l]) {
case 0x41 /*VT_BLOB*/: blob.l += 4; val = parse_BLOB(blob); break;
case 0x1E /*VT_LPSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/\u0000+$/,""); break;
case 0x1F /*VT_LPWSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/\u0000+$/,""); break;
case 0x1E /*VT_LPSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/(^|[^\u0000])\u0000+$/,"$1"); break;
case 0x1F /*VT_LPWSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/(^|[^\u0000])\u0000+$/,"$1"); break;
case 0x03 /*VT_I4*/: blob.l += 4; val = blob.read_shift(4, 'i'); break;
case 0x13 /*VT_UI4*/: blob.l += 4; val = blob.read_shift(4); break;
case 0x05 /*VT_R8*/: blob.l += 4; val = blob.read_shift(8, 'f'); break;

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

@ -1,62 +1,61 @@
/* from js-harb (C) 2014-present SheetJS */
var DBF_SUPPORTED_VERSIONS = [0x02, 0x03, 0x30, 0x31, 0x83, 0x8B, 0x8C, 0xF5];
var DBF = /*#__PURE__*/(function() {
var dbf_codepage_map = {
/* Code Pages Supported by Visual FoxPro */
/*::[*/0x01/*::]*/: 437, /*::[*/0x02/*::]*/: 850,
/*::[*/0x03/*::]*/: 1252, /*::[*/0x04/*::]*/: 10000,
/*::[*/0x64/*::]*/: 852, /*::[*/0x65/*::]*/: 866,
/*::[*/0x66/*::]*/: 865, /*::[*/0x67/*::]*/: 861,
/*::[*/0x68/*::]*/: 895, /*::[*/0x69/*::]*/: 620,
/*::[*/0x6A/*::]*/: 737, /*::[*/0x6B/*::]*/: 857,
/*::[*/0x78/*::]*/: 950, /*::[*/0x79/*::]*/: 949,
/*::[*/0x7A/*::]*/: 936, /*::[*/0x7B/*::]*/: 932,
/*::[*/0x7C/*::]*/: 874, /*::[*/0x7D/*::]*/: 1255,
/*::[*/0x7E/*::]*/: 1256, /*::[*/0x96/*::]*/: 10007,
/*::[*/0x97/*::]*/: 10029, /*::[*/0x98/*::]*/: 10006,
/*::[*/0xC8/*::]*/: 1250, /*::[*/0xC9/*::]*/: 1251,
/*::[*/0xCA/*::]*/: 1254, /*::[*/0xCB/*::]*/: 1253,
0x01: 437, 0x02: 850,
0x03: 1252, 0x04: 10000,
0x64: 852, 0x65: 866,
0x66: 865, 0x67: 861,
0x68: 895, 0x69: 620,
0x6A: 737, 0x6B: 857,
0x78: 950, 0x79: 949,
0x7A: 936, 0x7B: 932,
0x7C: 874, 0x7D: 1255,
0x7E: 1256, 0x96: 10007,
0x97: 10029, 0x98: 10006,
0xC8: 1250, 0xC9: 1251,
0xCA: 1254, 0xCB: 1253,
/* shapefile DBF extension */
/*::[*/0x00/*::]*/: 20127, /*::[*/0x08/*::]*/: 865,
/*::[*/0x09/*::]*/: 437, /*::[*/0x0A/*::]*/: 850,
/*::[*/0x0B/*::]*/: 437, /*::[*/0x0D/*::]*/: 437,
/*::[*/0x0E/*::]*/: 850, /*::[*/0x0F/*::]*/: 437,
/*::[*/0x10/*::]*/: 850, /*::[*/0x11/*::]*/: 437,
/*::[*/0x12/*::]*/: 850, /*::[*/0x13/*::]*/: 932,
/*::[*/0x14/*::]*/: 850, /*::[*/0x15/*::]*/: 437,
/*::[*/0x16/*::]*/: 850, /*::[*/0x17/*::]*/: 865,
/*::[*/0x18/*::]*/: 437, /*::[*/0x19/*::]*/: 437,
/*::[*/0x1A/*::]*/: 850, /*::[*/0x1B/*::]*/: 437,
/*::[*/0x1C/*::]*/: 863, /*::[*/0x1D/*::]*/: 850,
/*::[*/0x1F/*::]*/: 852, /*::[*/0x22/*::]*/: 852,
/*::[*/0x23/*::]*/: 852, /*::[*/0x24/*::]*/: 860,
/*::[*/0x25/*::]*/: 850, /*::[*/0x26/*::]*/: 866,
/*::[*/0x37/*::]*/: 850, /*::[*/0x40/*::]*/: 852,
/*::[*/0x4D/*::]*/: 936, /*::[*/0x4E/*::]*/: 949,
/*::[*/0x4F/*::]*/: 950, /*::[*/0x50/*::]*/: 874,
/*::[*/0x57/*::]*/: 1252, /*::[*/0x58/*::]*/: 1252,
/*::[*/0x59/*::]*/: 1252, /*::[*/0x6C/*::]*/: 863,
/*::[*/0x86/*::]*/: 737, /*::[*/0x87/*::]*/: 852,
/*::[*/0x88/*::]*/: 857, /*::[*/0xCC/*::]*/: 1257,
0x00: 20127, 0x08: 865,
0x09: 437, 0x0A: 850,
0x0B: 437, 0x0D: 437,
0x0E: 850, 0x0F: 437,
0x10: 850, 0x11: 437,
0x12: 850, 0x13: 932,
0x14: 850, 0x15: 437,
0x16: 850, 0x17: 865,
0x18: 437, 0x19: 437,
0x1A: 850, 0x1B: 437,
0x1C: 863, 0x1D: 850,
0x1F: 852, 0x22: 852,
0x23: 852, 0x24: 860,
0x25: 850, 0x26: 866,
0x37: 850, 0x40: 852,
0x4D: 936, 0x4E: 949,
0x4F: 950, 0x50: 874,
0x57: 1252, 0x58: 1252,
0x59: 1252, 0x6C: 863,
0x86: 737, 0x87: 852,
0x88: 857, 0xCC: 1257,
/*::[*/0xFF/*::]*/: 16969
0xFF: 16969
};
var dbf_reverse_map = evert({
/*::[*/0x01/*::]*/: 437, /*::[*/0x02/*::]*/: 850,
/*::[*/0x03/*::]*/: 1252, /*::[*/0x04/*::]*/: 10000,
/*::[*/0x64/*::]*/: 852, /*::[*/0x65/*::]*/: 866,
/*::[*/0x66/*::]*/: 865, /*::[*/0x67/*::]*/: 861,
/*::[*/0x68/*::]*/: 895, /*::[*/0x69/*::]*/: 620,
/*::[*/0x6A/*::]*/: 737, /*::[*/0x6B/*::]*/: 857,
/*::[*/0x78/*::]*/: 950, /*::[*/0x79/*::]*/: 949,
/*::[*/0x7A/*::]*/: 936, /*::[*/0x7B/*::]*/: 932,
/*::[*/0x7C/*::]*/: 874, /*::[*/0x7D/*::]*/: 1255,
/*::[*/0x7E/*::]*/: 1256, /*::[*/0x96/*::]*/: 10007,
/*::[*/0x97/*::]*/: 10029, /*::[*/0x98/*::]*/: 10006,
/*::[*/0xC8/*::]*/: 1250, /*::[*/0xC9/*::]*/: 1251,
/*::[*/0xCA/*::]*/: 1254, /*::[*/0xCB/*::]*/: 1253,
/*::[*/0x00/*::]*/: 20127
0x01: 437, 0x02: 850,
0x03: 1252, 0x04: 10000,
0x64: 852, 0x65: 866,
0x66: 865, 0x67: 861,
0x68: 895, 0x69: 620,
0x6A: 737, 0x6B: 857,
0x78: 950, 0x79: 949,
0x7A: 936, 0x7B: 932,
0x7C: 874, 0x7D: 1255,
0x7E: 1256, 0x96: 10007,
0x97: 10029, 0x98: 10006,
0xC8: 1250, 0xC9: 1251,
0xCA: 1254, 0xCB: 1253,
0x00: 20127
});
/* TODO: find an actual specification */
function dbf_to_aoa(buf, opts)/*:AOA*/ {
@ -119,7 +118,7 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
var ww = l7 ? 32 : 11;
while(d.l < hend && d[d.l] != 0x0d) {
field = ({}/*:any*/);
field.name = (typeof $cptable !== "undefined" ? $cptable.utils.decode(current_cp, d.slice(d.l, d.l+ww)) : a2s(d.slice(d.l, d.l + ww))).replace(/[\u0000\r\n].*$/g,"");
field.name = (typeof $cptable !== "undefined" ? $cptable.utils.decode(current_cp, d.slice(d.l, d.l+ww)) : a2s(d.slice(d.l, d.l + ww))).replace(/[\u0000\r\n][\S\s]*$/g,"");
d.l += ww;
field.type = String.fromCharCode(d.read_shift(1));
if(ft != 0x02 && !l7) field.offset = d.read_shift(4);
@ -177,10 +176,13 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
switch(fields[C].type) {
case 'C':
// NOTE: it is conventional to write ' / / ' for empty dates
if(s.trim().length) out[R][C] = s.replace(/\s+$/,"");
if(s.trim().length) out[R][C] = s.replace(/([^\s])\s+$/,"$1");
break;
case 'D':
if(s.length === 8) out[R][C] = new Date(+s.slice(0,4), +s.slice(4,6)-1, +s.slice(6,8));
if(s.length === 8) {
out[R][C] = new Date(Date.UTC(+s.slice(0,4), +s.slice(4,6)-1, +s.slice(6,8), 0, 0, 0, 0));
if(!(opts && opts.UTC)) { out[R][C] = utc_to_local(out[R][C]); }
}
else out[R][C] = s;
break;
case 'F': out[R][C] = parseFloat(s.trim()); break;
@ -188,7 +190,7 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
case 'L': switch(s.trim().toUpperCase()) {
case 'Y': case 'T': out[R][C] = true; break;
case 'N': case 'F': out[R][C] = false; break;
case '': case '?': break;
case '': case '\x00': case '?': break;
default: throw new Error("DBF Unrecognized L:|" + s + "|");
} break;
case 'M': /* TODO: handle memo files */
@ -203,7 +205,12 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
// NOTE: dBASE specs appear to be incorrect
out[R][C] = new Date(dd.read_shift(-8, 'f') - 0x388317533400);
break;
case 'T': out[R][C] = new Date((dd.read_shift(4) - 0x253D8C) * 0x5265C00 + dd.read_shift(4)); break;
case 'T': {
var hi = dd.read_shift(4), lo = dd.read_shift(4);
if(hi == 0 && lo == 0) break;
out[R][C] = new Date((hi - 0x253D8C) * 0x5265C00 + lo);
if(!(opts && opts.UTC)) out[R][C] = utc_to_local(out[R][C]);
} break;
case 'Y': out[R][C] = dd.read_shift(4,'i')/1e4 + (dd.read_shift(4, 'i')/1e4)*Math.pow(2,32); break;
case 'O': out[R][C] = -dd.read_shift(-8, 'f'); break;
case 'B': if(vfp && fields[C].len == 8) { out[R][C] = dd.read_shift(8,'f'); break; }
@ -239,14 +246,15 @@ function dbf_to_workbook(buf, opts)/*:Workbook*/ {
var o = sheet_to_workbook(dbf_to_sheet(buf, opts), opts);
o.bookType = "dbf";
return o;
}
catch(e) { if(opts && opts.WTF) throw e; }
} catch(e) { if(opts && opts.WTF) throw e; }
return ({SheetNames:[],Sheets:{}});
}
var _RLEN = { 'B': 8, 'C': 250, 'L': 1, 'D': 8, '?': 0, '': 0 };
function sheet_to_dbf(ws/*:Worksheet*/, opts/*:WriteOpts*/) {
if(!ws["!ref"]) throw new Error("Cannot export empty sheet to DBF");
var o = opts || {};
var old_cp = current_codepage;
if(+o.codepage >= 0) set_cp(+o.codepage);
if(o.type == "string") throw new Error("Cannot write DBF to JS string");
var ba = buf_array();
@ -282,7 +290,8 @@ function sheet_to_dbf(ws/*:Worksheet*/, opts/*:WriteOpts*/) {
case 'object': _guess = col[j] instanceof Date ? 'D' : 'C'; break;
default: _guess = 'C';
}
maxlen = Math.max(maxlen, String(col[j]).length);
/* TODO: cache the values instead of encoding twice */
maxlen = Math.max(maxlen, (typeof $cptable !== "undefined" && typeof col[j] == "string" ? $cptable.utils.encode(current_ansi, col[j]): String(col[j])).length);
guess = guess && guess != _guess ? 'C' : _guess;
//if(guess == 'C') break;
}
@ -308,11 +317,17 @@ function sheet_to_dbf(ws/*:Worksheet*/, opts/*:WriteOpts*/) {
h.write_shift(2, 296 + 32 * hcnt);
h.write_shift(2, rlen);
for(i=0; i < 4; ++i) h.write_shift(4, 0);
h.write_shift(4, 0x00000000 | ((+dbf_reverse_map[/*::String(*/current_ansi/*::)*/] || 0x03)<<8));
var cp = +dbf_reverse_map[/*::String(*/current_codepage/*::)*/] || 0x03;
h.write_shift(4, 0x00000000 | (cp<<8));
if(dbf_codepage_map[cp] != +o.codepage) {
if(o.codepage) console.error("DBF Unsupported codepage " + current_codepage + ", using 1252");
current_codepage = 1252;
}
for(i = 0, j = 0; i < headers.length; ++i) {
if(headers[i] == null) continue;
var hf = ba.next(32);
/* TODO: test how applications handle non-ASCII field names */
var _f = (headers[i].slice(-10) + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00").slice(0, 11);
hf.write_shift(1, _f, "sbcs");
hf.write_shift(1, coltypes[i] == '?' ? 'C' : coltypes[i], "sbcs");
@ -341,6 +356,7 @@ function sheet_to_dbf(ws/*:Worksheet*/, opts/*:WriteOpts*/) {
case 'N':
var _n = "0";
if(typeof data[i][j] == "number") _n = data[i][j].toFixed(coldecimals[j]||0);
if(_n.length > colwidths[j]) _n = _n.slice(0, colwidths[j]); // addresses decimal > width
for(hcnt=0; hcnt < colwidths[j]-_n.length; ++hcnt) rout.write_shift(1, 0x20);
rout.write_shift(1, _n, "sbcs");
break;
@ -352,13 +368,16 @@ function sheet_to_dbf(ws/*:Worksheet*/, opts/*:WriteOpts*/) {
rout.write_shift(2, ("00"+data[i][j].getDate()).slice(-2), "sbcs");
} break;
case 'C':
var _l = rout.l;
var _s = String(data[i][j] != null ? data[i][j] : "").slice(0, colwidths[j]);
rout.write_shift(1, _s, "sbcs");
for(hcnt=0; hcnt < colwidths[j]-_s.length; ++hcnt) rout.write_shift(1, 0x20); break;
rout.write_shift(1, _s, "cpstr");
_l += colwidths[j] - rout.l;
for(hcnt=0; hcnt < _l; ++hcnt) rout.write_shift(1, 0x20); break;
}
}
// data
}
current_codepage = old_cp;
ba.next(1).write_shift(1, 0x1A);
return ba.end();
}
@ -385,16 +404,21 @@ var SYLK = /*#__PURE__*/(function() {
KC:'Ç', Kc:'ç', q:'æ', z:'œ', a:'Æ', j:'Œ',
DN:209, Dn:241, Hy:255,
S:169, c:170, R:174, "B ":180,
/*::[*/0/*::]*/:176, /*::[*/1/*::]*/:177, /*::[*/2/*::]*/:178,
/*::[*/3/*::]*/:179, /*::[*/5/*::]*/:181, /*::[*/6/*::]*/:182,
/*::[*/7/*::]*/:183, Q:185, k:186, b:208, i:216, l:222, s:240, y:248,
0:176, 1:177, 2:178,
3:179, 5:181, 6:182,
7:183, Q:185, k:186, b:208, i:216, l:222, s:240, y:248,
"!":161, '"':162, "#":163, "(":164, "%":165, "'":167, "H ":168,
"+":171, ";":187, "<":188, "=":189, ">":190, "?":191, "{":223
}/*:any*/);
var sylk_char_regex = new RegExp("\u001BN(" + keys(sylk_escapes).join("|").replace(/\|\|\|/, "|\\||").replace(/([?()+])/g,"\\$1") + "|\\|)", "gm");
var sylk_char_regex = new RegExp("\u001BN(" + keys(sylk_escapes).join("|").replace(/\|\|\|/, "|\\||").replace(/([?()+])/g,"\\$1").replace("{", "\\{") + "|\\|)", "gm");
try {
sylk_char_regex = new RegExp("\u001BN(" + keys(sylk_escapes).join("|").replace(/\|\|\|/, "|\\||").replace(/([?()+])/g,"\\$1") + "|\\|)", "gm");
} catch(e) {}
var sylk_char_fn = function(_, $1){ var o = sylk_escapes[$1]; return typeof o == "number" ? _getansi(o) : o; };
var decode_sylk_char = function($$, $1, $2) { var newcc = (($1.charCodeAt(0) - 0x20)<<4) | ($2.charCodeAt(0) - 0x30); return newcc == 59 ? $$ : _getansi(newcc); };
sylk_escapes["|"] = 254;
/* TODO: evert the escape map */
var encode_sylk_str = function($$) { return $$.replace(/\n/g, "\x1b :").replace(/\r/g, "\x1b ="); };
/* https://oss.sheetjs.com/notes/sylk/ for more details */
function sylk_to_aoa(d/*:RawData*/, opts)/*:[AOA, Worksheet]*/ {
switch(opts.type) {
@ -447,8 +471,9 @@ var SYLK = /*#__PURE__*/(function() {
// case 'NU': // ??
case 'C': /* cell */
var C_seen_K = false, C_seen_X = false, C_seen_S = false, C_seen_E = false, _R = -1, _C = -1, formula = "", cell_t = "z";
var cmnt = "";
for(rj=1; rj<record.length; ++rj) switch(record[rj].charAt(0)) {
case 'A': break; // TODO: comment
case 'A': cmnt = record[rj].slice(1); break; // TODO: comment
case 'X': C = parseInt(record[rj].slice(1), 10)-1; C_seen_X = true; break;
case 'Y':
R = parseInt(record[rj].slice(1), 10)-1; if(!C_seen_X) C = 0;
@ -458,12 +483,12 @@ var SYLK = /*#__PURE__*/(function() {
val = record[rj].slice(1);
if(val.charAt(0) === '"') { val = val.slice(1,val.length - 1); cell_t = "s"; }
else if(val === 'TRUE' || val === 'FALSE') { val = val === 'TRUE'; cell_t = "b"; }
else if(val.charAt(0) == "#" && RBErr[val] != null) { cell_t = "e"; val = RBErr[val]; }
else if(!isNaN(fuzzynum(val))) {
val = fuzzynum(val); cell_t = "n";
if(next_cell_format !== null && fmt_is_date(next_cell_format) && opts.cellDates) { val = numdate(wb.Workbook.WBProps.date1904 ? val + 1462 : val); cell_t = "d"; }
} else if(!isNaN(fuzzydate(val).getDate())) {
val = parseDate(val); cell_t = "d";
if(!opts.cellDates) { cell_t = "n"; val = datenum(val, wb.Workbook.WBProps.date1904); }
if(next_cell_format !== null && fmt_is_date(next_cell_format) && opts.cellDates) {
val = numdate(wb.Workbook.WBProps.date1904 ? val + 1462 : val); cell_t = typeof val == "number" ? "n" : "d";
}
}
if(typeof $cptable !== 'undefined' && typeof val == "string" && ((opts||{}).type != "string") && (opts||{}).codepage) val = $cptable.utils.decode(opts.codepage, val);
C_seen_K = true;
@ -499,6 +524,10 @@ var SYLK = /*#__PURE__*/(function() {
if(!arr[R][C]) arr[R][C] = { t: 'n', f: formula };
else arr[R][C].f = formula;
}
if(cmnt) {
if(!arr[R][C]) arr[R][C] = { t: 'z' };
arr[R][C].c = [{a:"SheetJSYLK", t: cmnt}];
}
break;
case 'F': /* Format */
var F_seen = 0;
@ -560,20 +589,27 @@ var SYLK = /*#__PURE__*/(function() {
return outwb;
}
function write_ws_cell_sylk(cell/*:Cell*/, ws/*:Worksheet*/, R/*:number*/, C/*:number*//*::, opts*/)/*:string*/ {
function write_ws_cell_sylk(cell/*:Cell*/, ws/*:Worksheet*/, R/*:number*/, C/*:number*/, opts, date1904/*:boolean*/)/*:string*/ {
var o = "C;Y" + (R+1) + ";X" + (C+1) + ";K";
switch(cell.t) {
case 'n':
o += (cell.v||0);
o += isFinite(cell.v) ? (cell.v||0) : BErr[isNaN(cell.v) ? 0x24 : 0x07];
if(cell.f && !cell.F) o += ";E" + a1_to_rc(cell.f, {r:R, c:C}); break;
case 'b': o += cell.v ? "TRUE" : "FALSE"; break;
case 'e': o += cell.w || cell.v; break;
case 'd': o += '"' + (cell.w || cell.v) + '"'; break;
case 's': o += '"' + cell.v.replace(/"/g,"").replace(/;/g, ";;") + '"'; break;
case 'e': o += cell.w || BErr[cell.v] || cell.v; break;
case 'd': o += datenum(parseDate(cell.v, date1904), date1904); break;
case 's': o += '"' + (cell.v == null ? "" : String(cell.v)).replace(/"/g,"").replace(/;/g, ";;") + '"'; break;
}
return o;
}
function write_ws_cmnt_sylk(cmnt/*:Comment*/, R/*:number*/, C/*:number*/)/*:string*/ {
var o = "C;Y" + (R+1) + ";X" + (C+1) + ";A";
/* TODO: max length? */
o += encode_sylk_str(cmnt.map(function(c) { return c.t; }).join(""));
return o;
}
function write_ws_cols_sylk(out, cols) {
cols.forEach(function(col, i) {
var rec = "F;W" + (i+1) + " " + (i+1) + " ";
@ -598,29 +634,52 @@ var SYLK = /*#__PURE__*/(function() {
}
function sheet_to_sylk(ws/*:Worksheet*/, opts/*:?any*/, wb/*:?WorkBook*/)/*:string*/ {
if(!opts) opts = {}; opts._formats = ["General"];
/* TODO: codepage */
var preamble/*:Array<string>*/ = ["ID;PSheetJS;N;E"], o/*:Array<string>*/ = [];
var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
var dense = Array.isArray(ws);
var r = safe_decode_range(ws['!ref']||"A1"), cell/*:Cell*/;
var dense = ws["!data"] != null;
var RS = "\r\n";
var d1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
var _lastfmt = "General";
preamble.push("P;PGeneral");
/* Excel has been inconsistent in comment placement */
var R = r.s.r, C = r.s.c, p = [];
if(ws["!ref"]) for(R = r.s.r; R <= r.e.r; ++R) {
if(dense && !ws["!data"][R]) continue;
p = [];
for(C = r.s.c; C <= r.e.c; ++C) {
cell = dense ? ws["!data"][R][C] : ws[encode_col(C) + encode_row(R)];
if(!cell || !cell.c) continue;
p.push(write_ws_cmnt_sylk(cell.c, R, C));
}
if(p.length) o.push(p.join(RS));
}
if(ws["!ref"]) for(R = r.s.r; R <= r.e.r; ++R) {
if(dense && !ws["!data"][R]) continue;
p = [];
for(C = r.s.c; C <= r.e.c; ++C) {
cell = dense ? ws["!data"][R][C] : ws[encode_col(C) + encode_row(R)];
if(!cell || (cell.v == null && (!cell.f || cell.F))) continue;
if((cell.z||(cell.t == "d" ? table_fmt[14] : "General")) != _lastfmt) {
var ifmt = opts._formats.indexOf(cell.z);
if(ifmt == -1) { opts._formats.push(cell.z); ifmt = opts._formats.length - 1; preamble.push("P;P" + cell.z.replace(/;/g, ";;")); }
p.push("F;P" + ifmt + ";Y" + (R+1) + ";X" + (C+1));
}
p.push(write_ws_cell_sylk(cell, ws, R, C, opts, d1904));
}
o.push(p.join(RS));
}
preamble.push("F;P0;DG0G8;M255");
if(ws['!cols']) write_ws_cols_sylk(preamble, ws['!cols']);
if(ws['!rows']) write_ws_rows_sylk(preamble, ws['!rows']);
preamble.push("B;Y" + (r.e.r - r.s.r + 1) + ";X" + (r.e.c - r.s.c + 1) + ";D" + [r.s.c,r.s.r,r.e.c,r.e.r].join(" "));
if(ws["!ref"]) preamble.push("B;Y" + (r.e.r - r.s.r + 1) + ";X" + (r.e.c - r.s.c + 1) + ";D" + [r.s.c,r.s.r,r.e.c,r.e.r].join(" "));
preamble.push("O;L;D;B" + (d1904 ? ";V4" : "") + ";K47;G100 0.001");
for(var R = r.s.r; R <= r.e.r; ++R) {
var p = [];
for(var C = r.s.c; C <= r.e.c; ++C) {
var coord = encode_cell({r:R,c:C});
cell = dense ? (ws[R]||[])[C]: ws[coord];
if(!cell || (cell.v == null && (!cell.f || cell.F))) continue;
p.push(write_ws_cell_sylk(cell, ws, R, C, opts)); // TODO: pass date1904 info
}
o.push(p.join(RS));
}
delete opts._formats;
return preamble.join(RS) + RS + o.join(RS) + RS + "E" + RS;
}
@ -660,7 +719,10 @@ var DIF = /*#__PURE__*/(function() {
if(data === 'TRUE') arr[R][C] = true;
else if(data === 'FALSE') arr[R][C] = false;
else if(!isNaN(fuzzynum(value))) arr[R][C] = fuzzynum(value);
else if(!isNaN(fuzzydate(value).getDate())) arr[R][C] = parseDate(value);
else if(!isNaN(fuzzydate(value).getDate())) {
arr[R][C] = parseDate(value);
if(!(opts && opts.UTC)) { arr[R][C] = utc_to_local(arr[R][C]); }
}
else arr[R][C] = value;
++C; break;
case 1:
@ -683,62 +745,56 @@ var DIF = /*#__PURE__*/(function() {
return o;
}
var sheet_to_dif = /*#__PURE__*/(function() {
var push_field = function pf(o/*:Array<string>*/, topic/*:string*/, v/*:number*/, n/*:number*/, s/*:string*/) {
o.push(topic);
o.push(v + "," + n);
o.push('"' + s.replace(/"/g,'""') + '"');
};
var push_value = function po(o/*:Array<string>*/, type/*:number*/, v/*:any*/, s/*:string*/) {
o.push(type + "," + v);
o.push(type == 1 ? '"' + s.replace(/"/g,'""') + '"' : s);
};
return function sheet_to_dif(ws/*:Worksheet*//*::, opts:?any*/)/*:string*/ {
var o/*:Array<string>*/ = [];
var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
var dense = Array.isArray(ws);
push_field(o, "TABLE", 0, 1, "sheetjs");
push_field(o, "VECTORS", 0, r.e.r - r.s.r + 1,"");
push_field(o, "TUPLES", 0, r.e.c - r.s.c + 1,"");
push_field(o, "DATA", 0, 0,"");
for(var R = r.s.r; R <= r.e.r; ++R) {
push_value(o, -1, 0, "BOT");
for(var C = r.s.c; C <= r.e.c; ++C) {
var coord = encode_cell({r:R,c:C});
cell = dense ? (ws[R]||[])[C] : ws[coord];
if(!cell) { push_value(o, 1, 0, ""); continue;}
switch(cell.t) {
case 'n':
var val = DIF_XL ? cell.w : cell.v;
if(!val && cell.v != null) val = cell.v;
if(val == null) {
if(DIF_XL && cell.f && !cell.F) push_value(o, 1, 0, "=" + cell.f);
else push_value(o, 1, 0, "");
}
else push_value(o, 0, val, "V");
break;
case 'b':
push_value(o, 0, cell.v ? 1 : 0, cell.v ? "TRUE" : "FALSE");
break;
case 's':
push_value(o, 1, 0, (!DIF_XL || isNaN(cell.v)) ? cell.v : '="' + cell.v + '"');
break;
case 'd':
if(!cell.w) cell.w = SSF_format(cell.z || table_fmt[14], datenum(parseDate(cell.v)));
if(DIF_XL) push_value(o, 0, cell.w, "V");
else push_value(o, 1, 0, cell.w);
break;
default: push_value(o, 1, 0, "");
}
function make_value(v/*:number*/, s/*:string*/)/*:string*/ { return "0," + String(v) + "\r\n" + s; }
function make_value_str(s/*:string*/)/*:string*/ { return "1,0\r\n\"" + s.replace(/"/g,'""') + '"'; }
function sheet_to_dif(ws/*:Worksheet*//*::, opts:?any*/)/*:string*/ {
var _DIF_XL = DIF_XL;
if(!ws["!ref"]) throw new Error("Cannot export empty sheet to DIF");
var r = safe_decode_range(ws['!ref']);
var dense = ws["!data"] != null;
var o/*:Array<string>*/ = [
"TABLE\r\n0,1\r\n\"sheetjs\"\r\n",
"VECTORS\r\n0," + (r.e.r - r.s.r + 1) + "\r\n\"\"\r\n",
"TUPLES\r\n0," + (r.e.c - r.s.c + 1) + "\r\n\"\"\r\n",
"DATA\r\n0,0\r\n\"\"\r\n"
];
for(var R = r.s.r; R <= r.e.r; ++R) {
var row = dense ? ws["!data"][R] : [];
var p = "-1,0\r\nBOT\r\n";
for(var C = r.s.c; C <= r.e.c; ++C) {
var cell/*:Cell*/ = dense ? (row && row[C]) : ws[encode_cell({r:R,c:C})];
if(cell == null) { p +=("1,0\r\n\"\"\r\n"); continue;}
switch(cell.t) {
case 'n':
if(_DIF_XL) {
if(cell.w != null) p +=("0," + cell.w + "\r\nV");
else if(cell.v != null) p +=(make_value(cell.v, "V")); // TODO: should this call SSF_format?
else if(cell.f != null && !cell.F) p +=(make_value_str("=" + cell.f));
else p +=("1,0\r\n\"\"");
} else {
if(cell.v == null) p +=("1,0\r\n\"\"");
else p +=(make_value(cell.v, "V"));
}
break;
case 'b':
p +=(cell.v ? make_value(1, "TRUE") : make_value(0, "FALSE"));
break;
case 's':
p +=(make_value_str((!_DIF_XL || isNaN(+cell.v)) ? cell.v : '="' + cell.v + '"'));
break;
case 'd':
if(!cell.w) cell.w = SSF_format(cell.z || table_fmt[14], datenum(parseDate(cell.v)));
if(_DIF_XL) p +=(make_value(cell.w, "V"));
else p +=(make_value_str(cell.w));
break;
default: p +=("1,0\r\n\"\"");
}
p += "\r\n";
}
push_value(o, -1, 0, "EOD");
var RS = "\r\n";
var oo = o.join(RS);
//while((oo.length & 0x7F) != 0) oo += "\0";
return oo;
};
})();
o.push(p);
}
return o.join("") + "-1,0\r\nEOD";
}
return {
to_workbook: dif_to_workbook,
to_sheet: dif_to_sheet,
@ -766,7 +822,7 @@ var ETH = /*#__PURE__*/(function() {
case 'vtc':
switch(record[3]) {
case 'nl': arr[R][C] = +record[4] ? true : false; break;
default: arr[R][C] = +record[4]; break;
default: arr[R][C] = record[record.length-1].charAt(0) == "#" ? ({t: "e", v: RBErr[record[record.length-1]] }) : +record[4]; break;
}
if(record[2] == 'vtf') arr[R][C] = [arr[R][C], _f];
}
@ -801,19 +857,15 @@ var ETH = /*#__PURE__*/(function() {
if(!ws || !ws['!ref']) return "";
var o/*:Array<string>*/ = [], oo/*:Array<string>*/ = [], cell, coord = "";
var r = decode_range(ws['!ref']);
var dense = Array.isArray(ws);
var dense = ws["!data"] != null;
for(var R = r.s.r; R <= r.e.r; ++R) {
for(var C = r.s.c; C <= r.e.c; ++C) {
coord = encode_cell({r:R,c:C});
cell = dense ? (ws[R]||[])[C] : ws[coord];
cell = dense ? (ws["!data"][R]||[])[C] : ws[coord];
if(!cell || cell.v == null || cell.t === 'z') continue;
oo = ["cell", coord, 't'];
switch(cell.t) {
case 's': case 'str': oo.push(encode(cell.v)); break;
case 'n':
if(!cell.f) { oo[2]='v'; oo[3]=cell.v; }
else { oo[2]='vtf'; oo[3]='n'; oo[4]=cell.v; oo[5]=encode(cell.f); }
break;
case 's': oo.push(encode(cell.v)); break;
case 'b':
oo[2] = 'vt'+(cell.f?'f':'c'); oo[3]='nl'; oo[4]=cell.v?"1":"0";
oo[5] = encode(cell.f||(cell.v?'TRUE':'FALSE'));
@ -823,6 +875,19 @@ var ETH = /*#__PURE__*/(function() {
oo[2] = 'vtc'; oo[3] = 'nd'; oo[4] = ""+t;
oo[5] = cell.w || SSF_format(cell.z || table_fmt[14], t);
break;
case 'n':
if(isFinite(cell.v)) {
if(!cell.f) { oo[2]='v'; oo[3]=cell.v; }
else { oo[2]='vtf'; oo[3]='n'; oo[4]=cell.v; oo[5]=encode(cell.f); }
} else {
oo[2] = 'vt' + (cell.f ? 'f' : 'c');
oo[3] = "e" + BErr[isNaN(cell.v) ? 0x24 : 0x07];
oo[4] = "0";
oo[5] = cell.f || oo[3].slice(1);
oo[6] = "e";
oo[7] = oo[3].slice(1);
}
break;
case 'e': continue;
}
o.push(oo.join(":"));
@ -854,6 +919,7 @@ var PRN = /*#__PURE__*/(function() {
else if(data === 'FALSE') arr[R][C] = false;
else if(!isNaN(fuzzynum(data))) arr[R][C] = fuzzynum(data);
else if(!isNaN(fuzzydate(data).getDate())) arr[R][C] = parseDate(data);
else if(data.charCodeAt(0) == 35 /* # */ && RBErr[data] != null) arr[R][C] = ({ t: 'e', v: RBErr[data], w: data });
else arr[R][C] = data;
}
@ -885,18 +951,18 @@ var PRN = /*#__PURE__*/(function() {
// List of accepted CSV separators
var guess_seps = {
/*::[*/0x2C/*::]*/: ',',
/*::[*/0x09/*::]*/: "\t",
/*::[*/0x3B/*::]*/: ';',
/*::[*/0x7C/*::]*/: '|'
0x2C: ',',
0x09: "\t",
0x3B: ';',
0x7C: '|'
};
// CSV separator weights to be used in case of equal numbers
var guess_sep_weights = {
/*::[*/0x2C/*::]*/: 3,
/*::[*/0x09/*::]*/: 2,
/*::[*/0x3B/*::]*/: 1,
/*::[*/0x7C/*::]*/: 0
0x2C: 3,
0x09: 2,
0x3B: 1,
0x7C: 0
};
function guess_sep(str) {
@ -927,7 +993,8 @@ var PRN = /*#__PURE__*/(function() {
var o = opts || {};
var sep = "";
if(DENSE != null && o.dense == null) o.dense = DENSE;
var ws/*:Worksheet*/ = o.dense ? ([]/*:any*/) : ({}/*:any*/);
var ws/*:Worksheet*/ = ({}/*:any*/);
if(o.dense) ws["!data"] = [];
var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:0, r:0}}/*:any*/);
if(str.slice(0,4) == "sep=") {
@ -947,33 +1014,37 @@ var PRN = /*#__PURE__*/(function() {
var start = 0, end = 0, sepcc = sep.charCodeAt(0), instr = false, cc=0, startcc=str.charCodeAt(0);
var _re/*:?RegExp*/ = o.dateNF != null ? dateNF_regex(o.dateNF) : null;
function finish_cell() {
/* TODO: fuzzy parsers should pass back assumed number format */
var s = str.slice(start, end); if(s.slice(-1) == "\r") s = s.slice(0, -1);
var cell = ({}/*:any*/);
if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"');
if(o.cellText !== false) cell.w = s;
if(s.length === 0) cell.t = 'z';
else if(o.raw) { cell.t = 's'; cell.v = s; }
else if(s.trim().length === 0) { cell.t = 's'; cell.v = s; }
else if(s.charCodeAt(0) == 0x3D) {
if(s.charCodeAt(1) == 0x22 && s.charCodeAt(s.length - 1) == 0x22) { cell.t = 's'; cell.v = s.slice(2,-1).replace(/""/g,'"'); }
else if(fuzzyfmla(s)) { cell.t = 'n'; cell.f = s.slice(1); }
else if(fuzzyfmla(s)) { cell.t = 's'; cell.f = s.slice(1); cell.v = s; }
else { cell.t = 's'; cell.v = s; } }
else if(s == "TRUE") { cell.t = 'b'; cell.v = true; }
else if(s == "FALSE") { cell.t = 'b'; cell.v = false; }
else if(!isNaN(v = fuzzynum(s))) { cell.t = 'n'; if(o.cellText !== false) cell.w = s; cell.v = v; }
else if(!isNaN(v = fuzzynum(s))) { cell.t = 'n'; cell.v = v; }
else if(!isNaN((v = fuzzydate(s)).getDate()) || _re && s.match(_re)) {
cell.z = o.dateNF || table_fmt[14];
var k = 0;
if(_re && s.match(_re)){ s=dateNF_fix(s, o.dateNF, (s.match(_re)||[])); k=1; v = parseDate(s, k); }
if(_re && s.match(_re)){ var news=dateNF_fix(s, o.dateNF, (s.match(_re)||[])); v = parseDate(news); if(o && o.UTC === false) v = utc_to_local(v); }
else if(o && o.UTC === false) v = utc_to_local(v);
else if(o.cellText !== false && o.dateNF) cell.w = SSF_format(cell.z, v);
if(o.cellDates) { cell.t = 'd'; cell.v = v; }
else { cell.t = 'n'; cell.v = datenum(v); }
if(o.cellText !== false) cell.w = SSF_format(cell.z, cell.v instanceof Date ? datenum(cell.v):cell.v);
if(!o.cellNF) delete cell.z;
} else if(s.charCodeAt(0) == 35 /* # */ && RBErr[s] != null) {
cell.t = 'e'; cell.w = s; cell.v = RBErr[s];
} else {
cell.t = 's';
cell.v = s;
}
if(cell.t == 'z'){}
else if(o.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = cell; }
else if(o.dense) { if(!ws["!data"][R]) ws["!data"][R] = []; ws["!data"][R][C] = cell; }
else ws[encode_cell({c:C,r:R})] = cell;
start = end+1; startcc = str.charCodeAt(start);
if(range.e.c < C) range.e.c = C;
@ -1028,13 +1099,14 @@ var PRN = /*#__PURE__*/(function() {
function sheet_to_prn(ws/*:Worksheet*//*::, opts:?any*/)/*:string*/ {
var o/*:Array<string>*/ = [];
if(!ws["!ref"]) return "";
var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
var dense = Array.isArray(ws);
var dense = ws["!data"] != null;
for(var R = r.s.r; R <= r.e.r; ++R) {
var oo/*:Array<string>*/ = [];
for(var C = r.s.c; C <= r.e.c; ++C) {
var coord = encode_cell({r:R,c:C});
cell = dense ? (ws[R]||[])[C] : ws[coord];
cell = dense ? (ws["!data"][R]||[])[C] : ws[coord];
if(!cell || cell.v == null) { oo.push(" "); continue; }
var w = (cell.w || (format_cell(cell), cell.w) || "").slice(0,10);
while(w.length < 10) w += " ";
@ -1061,8 +1133,22 @@ function read_wb_ID(d, opts) {
return out;
} catch(e) {
o.WTF = OLD_WTF;
if(!e.message.match(/SYLK bad record ID/) && OLD_WTF) throw e;
if((e.message.indexOf("SYLK bad record ID") == -1) && OLD_WTF) throw e;
return PRN.to_workbook(d, opts);
}
}
function read_wb_TABL(d, opts) {
var o = opts || {}, OLD_WTF = !!o.WTF; o.WTF = true;
try {
var out = DIF.to_workbook(d, o);
if(!out || !out.Sheets) throw "DIF bad workbook";
var ws = out.Sheets[out.SheetNames[0]];
if(!ws || !ws["!ref"]) throw "DIF empty worksheet";
o.WTF = OLD_WTF;
return out;
} catch(e) {
o.WTF = OLD_WTF;
return PRN.to_workbook(d, opts);
}
}

@ -24,15 +24,33 @@ var WK_ = /*#__PURE__*/(function() {
throw "Unsupported type " + opts.type;
}
/* NOTE: this list intentionally starts at 1 */
var LOTUS_DATE_FMTS = [
"mmmm",
"dd-mmm-yyyy",
"dd-mmm",
"mmm-yyyy",
"@", // "text"?
"mm/dd",
"hh:mm:ss AM/PM", // 7
"hh:mm AM/PM",
"mm/dd/yyyy",
"mm/dd",
"hh:mm:ss",
"hh:mm" // 12
];
function lotus_to_workbook_buf(d, opts)/*:Workbook*/ {
if(!d) return d;
var o = opts || {};
if(DENSE != null && o.dense == null) o.dense = DENSE;
var s/*:Worksheet*/ = ((o.dense ? [] : {})/*:any*/), n = "Sheet1", next_n = "", sidx = 0;
var sheets = {}, snames = [], realnames = [];
var s/*:Worksheet*/ = ({}/*:any*/), n = "Sheet1", next_n = "", sidx = 0;
var sheets = {}, snames = [], realnames = [], sdata = [];
if(o.dense) sdata = s["!data"] = [];
var refguess = {s: {r:0, c:0}, e: {r:0, c:0} };
var sheetRows = o.sheetRows || 0;
var lastcell = {};
if(d[4] == 0x51 && d[5] == 0x50 && d[6] == 0x57) return qpw_to_workbook_buf(d, opts);
if(d[2] == 0x00) {
@ -64,9 +82,9 @@ var WK_ = /*#__PURE__*/(function() {
case 0x0E: /* NUMBER */
case 0x10: /* FORMULA */
/* TODO: actual translation of the format code */
if(RT == 0x0E && (val[2] & 0x70) == 0x70 && (val[2] & 0x0F) > 1 && (val[2] & 0x0F) < 15) {
val[1].z = o.dateNF || table_fmt[14];
if(o.cellDates) { val[1].t = 'd'; val[1].v = numdate(val[1].v); }
if((val[2] & 0x70) == 0x70 && (val[2] & 0x0F) > 1 && (val[2] & 0x0F) < 15) {
val[1].z = o.dateNF || LOTUS_DATE_FMTS[(val[2] & 0x0F)-1] || table_fmt[14];
if(o.cellDates) { val[1].v = numdate(val[1].v); val[1].t = typeof val[1].v == "number" ? 'n' : 'd'; }
}
if(o.qpro) {
@ -74,26 +92,36 @@ var WK_ = /*#__PURE__*/(function() {
s["!ref"] = encode_range(refguess);
sheets[n] = s;
snames.push(n);
s = (o.dense ? [] : {});
s = ({}/*:any*/); if(o.dense) sdata = s["!data"] = [];
refguess = {s: {r:0, c:0}, e: {r:0, c:0} };
sidx = val[3]; n = next_n || "Sheet" + (sidx + 1); next_n = "";
}
}
var tmpcell = o.dense ? (s[val[0].r]||[])[val[0].c] : s[encode_cell(val[0])];
var tmpcell = o.dense ? (sdata[val[0].r]||[])[val[0].c] : s[encode_cell(val[0])];
if(tmpcell) {
tmpcell.t = val[1].t; tmpcell.v = val[1].v;
if(val[1].z != null) tmpcell.z = val[1].z;
if(val[1].f != null) tmpcell.f = val[1].f;
lastcell = tmpcell;
break;
}
if(o.dense) {
if(!s[val[0].r]) s[val[0].r] = [];
s[val[0].r][val[0].c] = val[1];
if(!sdata[val[0].r]) sdata[val[0].r] = [];
sdata[val[0].r][val[0].c] = val[1];
} else s[encode_cell(val[0])] = val[1];
lastcell = val[1];
break;
case 0x5405: o.works2 = true; break;
default:
case 0x5402: {
/* TODO: enumerate all extended number formats */
if(val == 0x14a1) {
lastcell.z = "hh:mm:ss";
if(o.cellDates && lastcell.t == "n") {
lastcell.v = numdate(lastcell.v); lastcell.t = typeof lastcell.v == "number" ? 'n' : 'd';
}
}
} break;
}}, o);
} else if(d[2] == 0x1A || d[2] == 0x0E) {
o.Enum = WK3Enum;
@ -115,14 +143,14 @@ var WK_ = /*#__PURE__*/(function() {
s["!ref"] = encode_range(refguess);
sheets[n] = s;
snames.push(n);
s = (o.dense ? [] : {});
s = ({}/*:any*/); if(o.dense) sdata = s["!data"] = [];
refguess = {s: {r:0, c:0}, e: {r:0, c:0} };
sidx = val[3]; n = "Sheet" + (sidx + 1);
}
if(sheetRows > 0 && val[0].r >= sheetRows) break;
if(o.dense) {
if(!s[val[0].r]) s[val[0].r] = [];
s[val[0].r][val[0].c] = val[1];
if(!sdata[val[0].r]) sdata[val[0].r] = [];
sdata[val[0].r][val[0].c] = val[1];
} else s[encode_cell(val[0])] = val[1];
if(refguess.e.c < val[0].c) refguess.e.c = val[0].c;
if(refguess.e.r < val[0].r) refguess.e.r = val[0].r;
@ -156,25 +184,32 @@ var WK_ = /*#__PURE__*/(function() {
if(+o.codepage >= 0) set_cp(+o.codepage);
if(o.type == "string") throw new Error("Cannot write WK1 to JS string");
var ba = buf_array();
if(!ws["!ref"]) throw new Error("Cannot export empty sheet to WK1");
var range = safe_decode_range(ws["!ref"]);
var dense = Array.isArray(ws);
var dense = ws["!data"] != null;
var cols = [];
write_biff_rec(ba, 0x00, write_BOF_WK1(0x0406));
write_biff_rec(ba, 0x06, write_RANGE(range));
var max_R = Math.min(range.e.r, 8191);
for(var C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
for(var R = range.s.r; R <= max_R; ++R) {
var rr = encode_row(R);
for(var C = range.s.c; C <= range.e.c; ++C) {
if(R === range.s.r) cols[C] = encode_col(C);
var ref = cols[C] + rr;
var cell = dense ? (ws[R]||[])[C] : ws[ref];
for(C = range.s.c; C <= range.e.c; ++C) {
var cell = dense ? (ws["!data"][R]||[])[C] : ws[cols[C] + rr];
if(!cell || cell.t == "z") continue;
/* TODO: formula records */
if(cell.t == "n") {
if((cell.v|0)==cell.v && cell.v >= -32768 && cell.v <= 32767) write_biff_rec(ba, 0x0d, write_INTEGER(R, C, cell.v));
else write_biff_rec(ba, 0x0e, write_NUMBER(R, C, cell.v));
} else {
switch(cell.t) {
case "n":
if((cell.v|0)==cell.v && cell.v >= -32768 && cell.v <= 32767) write_biff_rec(ba, 0x0d, write_INTEGER(R, C, cell));
else write_biff_rec(ba, 0x0e, write_NUMBER(R, C, cell));
break;
case "d":
var dc = datenum(cell.v);
if((dc|0)==dc && dc >= -32768 && dc <= 32767) write_biff_rec(ba, 0x0d, write_INTEGER(R, C, {t:"n", v:dc, z:cell.z || table_fmt[14]}));
else write_biff_rec(ba, 0x0e, write_NUMBER(R, C, {t:"n", v:dc, z:cell.z || table_fmt[14]}));
break;
default:
var str = format_cell(cell);
write_biff_rec(ba, 0x0F, write_LABEL(R, C, str.slice(0, 239)));
}
@ -200,7 +235,7 @@ var WK_ = /*#__PURE__*/(function() {
var ws = wb.Sheets[wb.SheetNames[i]];
if(!ws || !ws["!ref"]) continue;
var range = safe_decode_range(ws["!ref"]);
var dense = Array.isArray(ws);
var dense = ws["!data"] != null;
var cols = [];
var max_R = Math.min(range.e.r, 8191);
for(var R = range.s.r; R <= max_R; ++R) {
@ -208,7 +243,7 @@ var WK_ = /*#__PURE__*/(function() {
for(var C = range.s.c; C <= range.e.c; ++C) {
if(R === range.s.r) cols[C] = encode_col(C);
var ref = cols[C] + rr;
var cell = dense ? (ws[R]||[])[C] : ws[ref];
var cell = dense ? (ws["!data"][R]||[])[C] : ws[ref];
if(!cell || cell.t == "z") continue;
/* TODO: FORMULA19 NUMBER18 records */
if(cell.t == "n") {
@ -308,11 +343,18 @@ var WK_ = /*#__PURE__*/(function() {
return o;
}
function get_wk1_fmt(cell)/*:number*/ {
/* TODO: some fuzzy matching on the number format */
if(cell.z && fmt_is_date(cell.z)) {
return 0xf0 | (LOTUS_DATE_FMTS.indexOf(cell.z) + 1 || 2);
}
return 0xFF;
}
function parse_LABEL(blob, length, opts) {
var tgt = blob.l + length;
var o = parse_cell(blob, length, opts);
o[1].t = 's';
if(opts.vers == 0x5120) {
if((opts.vers & 0xFFFE) == 0x5120) { // WQ1 / WQ2
blob.l++;
var len = blob.read_shift(1);
o[1].v = blob.read_shift(len, 'utf8');
@ -354,12 +396,12 @@ var WK_ = /*#__PURE__*/(function() {
o[1].v = blob.read_shift(2, 'i');
return o;
}
function write_INTEGER(R, C, v) {
function write_INTEGER(R, C, cell) {
var o = new_buf(7);
o.write_shift(1, 0xFF);
o.write_shift(1, get_wk1_fmt(cell));
o.write_shift(2, C);
o.write_shift(2, R);
o.write_shift(2, v, 'i');
o.write_shift(2, cell.v, 'i');
return o;
}
@ -368,12 +410,12 @@ var WK_ = /*#__PURE__*/(function() {
o[1].v = blob.read_shift(8, 'f');
return o;
}
function write_NUMBER(R, C, v) {
function write_NUMBER(R, C, cell) {
var o = new_buf(13);
o.write_shift(1, 0xFF);
o.write_shift(1, get_wk1_fmt(cell));
o.write_shift(2, C);
o.write_shift(2, R);
o.write_shift(8, v, 'f');
o.write_shift(8, cell.v, 'f');
return o;
}
@ -426,7 +468,7 @@ var WK_ = /*#__PURE__*/(function() {
0x33: ["FALSE", 0],
0x34: ["TRUE", 0],
0x35: ["RAND", 0],
// 0x36 DATE
0x36: ["DATE", 3],
// 0x37 NOW
// 0x38 PMT
// 0x39 PV
@ -436,7 +478,7 @@ var WK_ = /*#__PURE__*/(function() {
// 0x3D MONTH
// 0x3E YEAR
0x3F: ["ROUND", 2],
// 0x40 TIME
0x40: ["TIME", 3],
// 0x41 HOUR
// 0x42 MINUTE
// 0x43 SECOND
@ -556,7 +598,6 @@ var WK_ = /*#__PURE__*/(function() {
else console.error("WK1 bad formula parse |" + out.join("|") + "|");
}
function parse_cell_3(blob/*::, length*/) {
var o = [{c:0,r:0}, {t:'n',v:0}, 0];
o[0].r = blob.read_shift(2); o[3] = blob[blob.l++]; o[0].c = blob[blob.l++];
@ -721,209 +762,251 @@ var WK_ = /*#__PURE__*/(function() {
}
var WK1Enum = {
/*::[*/0x0000/*::]*/: { n:"BOF", f:parseuint16 },
/*::[*/0x0001/*::]*/: { n:"EOF" },
/*::[*/0x0002/*::]*/: { n:"CALCMODE" },
/*::[*/0x0003/*::]*/: { n:"CALCORDER" },
/*::[*/0x0004/*::]*/: { n:"SPLIT" },
/*::[*/0x0005/*::]*/: { n:"SYNC" },
/*::[*/0x0006/*::]*/: { n:"RANGE", f:parse_RANGE },
/*::[*/0x0007/*::]*/: { n:"WINDOW1" },
/*::[*/0x0008/*::]*/: { n:"COLW1" },
/*::[*/0x0009/*::]*/: { n:"WINTWO" },
/*::[*/0x000A/*::]*/: { n:"COLW2" },
/*::[*/0x000B/*::]*/: { n:"NAME" },
/*::[*/0x000C/*::]*/: { n:"BLANK" },
/*::[*/0x000D/*::]*/: { n:"INTEGER", f:parse_INTEGER },
/*::[*/0x000E/*::]*/: { n:"NUMBER", f:parse_NUMBER },
/*::[*/0x000F/*::]*/: { n:"LABEL", f:parse_LABEL },
/*::[*/0x0010/*::]*/: { n:"FORMULA", f:parse_FORMULA },
/*::[*/0x0018/*::]*/: { n:"TABLE" },
/*::[*/0x0019/*::]*/: { n:"ORANGE" },
/*::[*/0x001A/*::]*/: { n:"PRANGE" },
/*::[*/0x001B/*::]*/: { n:"SRANGE" },
/*::[*/0x001C/*::]*/: { n:"FRANGE" },
/*::[*/0x001D/*::]*/: { n:"KRANGE1" },
/*::[*/0x0020/*::]*/: { n:"HRANGE" },
/*::[*/0x0023/*::]*/: { n:"KRANGE2" },
/*::[*/0x0024/*::]*/: { n:"PROTEC" },
/*::[*/0x0025/*::]*/: { n:"FOOTER" },
/*::[*/0x0026/*::]*/: { n:"HEADER" },
/*::[*/0x0027/*::]*/: { n:"SETUP" },
/*::[*/0x0028/*::]*/: { n:"MARGINS" },
/*::[*/0x0029/*::]*/: { n:"LABELFMT" },
/*::[*/0x002A/*::]*/: { n:"TITLES" },
/*::[*/0x002B/*::]*/: { n:"SHEETJS" },
/*::[*/0x002D/*::]*/: { n:"GRAPH" },
/*::[*/0x002E/*::]*/: { n:"NGRAPH" },
/*::[*/0x002F/*::]*/: { n:"CALCCOUNT" },
/*::[*/0x0030/*::]*/: { n:"UNFORMATTED" },
/*::[*/0x0031/*::]*/: { n:"CURSORW12" },
/*::[*/0x0032/*::]*/: { n:"WINDOW" },
/*::[*/0x0033/*::]*/: { n:"STRING", f:parse_STRING },
/*::[*/0x0037/*::]*/: { n:"PASSWORD" },
/*::[*/0x0038/*::]*/: { n:"LOCKED" },
/*::[*/0x003C/*::]*/: { n:"QUERY" },
/*::[*/0x003D/*::]*/: { n:"QUERYNAME" },
/*::[*/0x003E/*::]*/: { n:"PRINT" },
/*::[*/0x003F/*::]*/: { n:"PRINTNAME" },
/*::[*/0x0040/*::]*/: { n:"GRAPH2" },
/*::[*/0x0041/*::]*/: { n:"GRAPHNAME" },
/*::[*/0x0042/*::]*/: { n:"ZOOM" },
/*::[*/0x0043/*::]*/: { n:"SYMSPLIT" },
/*::[*/0x0044/*::]*/: { n:"NSROWS" },
/*::[*/0x0045/*::]*/: { n:"NSCOLS" },
/*::[*/0x0046/*::]*/: { n:"RULER" },
/*::[*/0x0047/*::]*/: { n:"NNAME" },
/*::[*/0x0048/*::]*/: { n:"ACOMM" },
/*::[*/0x0049/*::]*/: { n:"AMACRO" },
/*::[*/0x004A/*::]*/: { n:"PARSE" },
/*::[*/0x0066/*::]*/: { n:"PRANGES??" },
/*::[*/0x0067/*::]*/: { n:"RRANGES??" },
/*::[*/0x0068/*::]*/: { n:"FNAME??" },
/*::[*/0x0069/*::]*/: { n:"MRANGES??" },
/*::[*/0x00CC/*::]*/: { n:"SHEETNAMECS", f:parse_SHEETNAMECS },
/*::[*/0x00DE/*::]*/: { n:"SHEETNAMELP", f:parse_SHEETNAMELP },
/*::[*/0x00FF/*::]*/: { n:"BOF", f:parseuint16 },
/*::[*/0xFFFF/*::]*/: { n:"" }
0x0000: { n:"BOF", f:parseuint16 },
0x0001: { n:"EOF" },
0x0002: { n:"CALCMODE" },
0x0003: { n:"CALCORDER" },
0x0004: { n:"SPLIT" },
0x0005: { n:"SYNC" },
0x0006: { n:"RANGE", f:parse_RANGE },
0x0007: { n:"WINDOW1" },
0x0008: { n:"COLW1" },
0x0009: { n:"WINTWO" },
0x000A: { n:"COLW2" },
0x000B: { n:"NAME" },
0x000C: { n:"BLANK" },
0x000D: { n:"INTEGER", f:parse_INTEGER },
0x000E: { n:"NUMBER", f:parse_NUMBER },
0x000F: { n:"LABEL", f:parse_LABEL },
0x0010: { n:"FORMULA", f:parse_FORMULA },
0x0018: { n:"TABLE" },
0x0019: { n:"ORANGE" },
0x001A: { n:"PRANGE" },
0x001B: { n:"SRANGE" },
0x001C: { n:"FRANGE" },
0x001D: { n:"KRANGE1" },
0x0020: { n:"HRANGE" },
0x0023: { n:"KRANGE2" },
0x0024: { n:"PROTEC" },
0x0025: { n:"FOOTER" },
0x0026: { n:"HEADER" },
0x0027: { n:"SETUP" },
0x0028: { n:"MARGINS" },
0x0029: { n:"LABELFMT" },
0x002A: { n:"TITLES" },
0x002B: { n:"SHEETJS" },
0x002D: { n:"GRAPH" },
0x002E: { n:"NGRAPH" },
0x002F: { n:"CALCCOUNT" },
0x0030: { n:"UNFORMATTED" },
0x0031: { n:"CURSORW12" },
0x0032: { n:"WINDOW" },
0x0033: { n:"STRING", f:parse_STRING },
0x0037: { n:"PASSWORD" },
0x0038: { n:"LOCKED" },
0x003C: { n:"QUERY" },
0x003D: { n:"QUERYNAME" },
0x003E: { n:"PRINT" },
0x003F: { n:"PRINTNAME" },
0x0040: { n:"GRAPH2" },
0x0041: { n:"GRAPHNAME" },
0x0042: { n:"ZOOM" },
0x0043: { n:"SYMSPLIT" },
0x0044: { n:"NSROWS" },
0x0045: { n:"NSCOLS" },
0x0046: { n:"RULER" },
0x0047: { n:"NNAME" },
0x0048: { n:"ACOMM" },
0x0049: { n:"AMACRO" },
0x004A: { n:"PARSE" },
// 0x0064
0x0066: { n:"PRANGES??" },
0x0067: { n:"RRANGES??" },
0x0068: { n:"FNAME??" },
0x0069: { n:"MRANGES??" },
// 0x0096
// 0x0099
// 0x009A
// 0x009B
// 0x009C
// 0x00C0
// 0x00C7
// 0x00C9
0x00CC: { n:"SHEETNAMECS", f:parse_SHEETNAMECS },
// 0x00CD
0x00DE: { n:"SHEETNAMELP", f:parse_SHEETNAMELP },
0x00FF: { n:"BOF", f:parseuint16 },
0x5402: { n:"WKSNF", f:parseuint16 },
0xFFFF: { n:"" }
};
var WK3Enum = {
/*::[*/0x0000/*::]*/: { n:"BOF" },
/*::[*/0x0001/*::]*/: { n:"EOF" },
/*::[*/0x0002/*::]*/: { n:"PASSWORD" },
/*::[*/0x0003/*::]*/: { n:"CALCSET" },
/*::[*/0x0004/*::]*/: { n:"WINDOWSET" },
/*::[*/0x0005/*::]*/: { n:"SHEETCELLPTR" },
/*::[*/0x0006/*::]*/: { n:"SHEETLAYOUT" },
/*::[*/0x0007/*::]*/: { n:"COLUMNWIDTH" },
/*::[*/0x0008/*::]*/: { n:"HIDDENCOLUMN" },
/*::[*/0x0009/*::]*/: { n:"USERRANGE" },
/*::[*/0x000A/*::]*/: { n:"SYSTEMRANGE" },
/*::[*/0x000B/*::]*/: { n:"ZEROFORCE" },
/*::[*/0x000C/*::]*/: { n:"SORTKEYDIR" },
/*::[*/0x000D/*::]*/: { n:"FILESEAL" },
/*::[*/0x000E/*::]*/: { n:"DATAFILLNUMS" },
/*::[*/0x000F/*::]*/: { n:"PRINTMAIN" },
/*::[*/0x0010/*::]*/: { n:"PRINTSTRING" },
/*::[*/0x0011/*::]*/: { n:"GRAPHMAIN" },
/*::[*/0x0012/*::]*/: { n:"GRAPHSTRING" },
/*::[*/0x0013/*::]*/: { n:"??" },
/*::[*/0x0014/*::]*/: { n:"ERRCELL" },
/*::[*/0x0015/*::]*/: { n:"NACELL" },
/*::[*/0x0016/*::]*/: { n:"LABEL16", f:parse_LABEL_16},
/*::[*/0x0017/*::]*/: { n:"NUMBER17", f:parse_NUMBER_17 },
/*::[*/0x0018/*::]*/: { n:"NUMBER18", f:parse_NUMBER_18 },
/*::[*/0x0019/*::]*/: { n:"FORMULA19", f:parse_FORMULA_19},
/*::[*/0x001A/*::]*/: { n:"FORMULA1A" },
/*::[*/0x001B/*::]*/: { n:"XFORMAT", f:parse_XFORMAT },
/*::[*/0x001C/*::]*/: { n:"DTLABELMISC" },
/*::[*/0x001D/*::]*/: { n:"DTLABELCELL" },
/*::[*/0x001E/*::]*/: { n:"GRAPHWINDOW" },
/*::[*/0x001F/*::]*/: { n:"CPA" },
/*::[*/0x0020/*::]*/: { n:"LPLAUTO" },
/*::[*/0x0021/*::]*/: { n:"QUERY" },
/*::[*/0x0022/*::]*/: { n:"HIDDENSHEET" },
/*::[*/0x0023/*::]*/: { n:"??" },
/*::[*/0x0025/*::]*/: { n:"NUMBER25", f:parse_NUMBER_25 },
/*::[*/0x0026/*::]*/: { n:"??" },
/*::[*/0x0027/*::]*/: { n:"NUMBER27", f:parse_NUMBER_27 },
/*::[*/0x0028/*::]*/: { n:"FORMULA28", f:parse_FORMULA_28 },
/*::[*/0x008E/*::]*/: { n:"??" },
/*::[*/0x0093/*::]*/: { n:"??" },
/*::[*/0x0096/*::]*/: { n:"??" },
/*::[*/0x0097/*::]*/: { n:"??" },
/*::[*/0x0098/*::]*/: { n:"??" },
/*::[*/0x0099/*::]*/: { n:"??" },
/*::[*/0x009A/*::]*/: { n:"??" },
/*::[*/0x009B/*::]*/: { n:"??" },
/*::[*/0x009C/*::]*/: { n:"??" },
/*::[*/0x00A3/*::]*/: { n:"??" },
/*::[*/0x00AE/*::]*/: { n:"??" },
/*::[*/0x00AF/*::]*/: { n:"??" },
/*::[*/0x00B0/*::]*/: { n:"??" },
/*::[*/0x00B1/*::]*/: { n:"??" },
/*::[*/0x00B8/*::]*/: { n:"??" },
/*::[*/0x00B9/*::]*/: { n:"??" },
/*::[*/0x00BA/*::]*/: { n:"??" },
/*::[*/0x00BB/*::]*/: { n:"??" },
/*::[*/0x00BC/*::]*/: { n:"??" },
/*::[*/0x00C3/*::]*/: { n:"??" },
/*::[*/0x00C9/*::]*/: { n:"??" },
/*::[*/0x00CC/*::]*/: { n:"SHEETNAMECS", f:parse_SHEETNAMECS },
/*::[*/0x00CD/*::]*/: { n:"??" },
/*::[*/0x00CE/*::]*/: { n:"??" },
/*::[*/0x00CF/*::]*/: { n:"??" },
/*::[*/0x00D0/*::]*/: { n:"??" },
/*::[*/0x0100/*::]*/: { n:"??" },
/*::[*/0x0103/*::]*/: { n:"??" },
/*::[*/0x0104/*::]*/: { n:"??" },
/*::[*/0x0105/*::]*/: { n:"??" },
/*::[*/0x0106/*::]*/: { n:"??" },
/*::[*/0x0107/*::]*/: { n:"??" },
/*::[*/0x0109/*::]*/: { n:"??" },
/*::[*/0x010A/*::]*/: { n:"??" },
/*::[*/0x010B/*::]*/: { n:"??" },
/*::[*/0x010C/*::]*/: { n:"??" },
/*::[*/0x010E/*::]*/: { n:"??" },
/*::[*/0x010F/*::]*/: { n:"??" },
/*::[*/0x0180/*::]*/: { n:"??" },
/*::[*/0x0185/*::]*/: { n:"??" },
/*::[*/0x0186/*::]*/: { n:"??" },
/*::[*/0x0189/*::]*/: { n:"??" },
/*::[*/0x018C/*::]*/: { n:"??" },
/*::[*/0x0200/*::]*/: { n:"??" },
/*::[*/0x0202/*::]*/: { n:"??" },
/*::[*/0x0201/*::]*/: { n:"??" },
/*::[*/0x0204/*::]*/: { n:"??" },
/*::[*/0x0205/*::]*/: { n:"??" },
/*::[*/0x0280/*::]*/: { n:"??" },
/*::[*/0x0281/*::]*/: { n:"??" },
/*::[*/0x0282/*::]*/: { n:"??" },
/*::[*/0x0283/*::]*/: { n:"??" },
/*::[*/0x0284/*::]*/: { n:"??" },
/*::[*/0x0285/*::]*/: { n:"??" },
/*::[*/0x0286/*::]*/: { n:"??" },
/*::[*/0x0287/*::]*/: { n:"??" },
/*::[*/0x0288/*::]*/: { n:"??" },
/*::[*/0x0292/*::]*/: { n:"??" },
/*::[*/0x0293/*::]*/: { n:"??" },
/*::[*/0x0294/*::]*/: { n:"??" },
/*::[*/0x0295/*::]*/: { n:"??" },
/*::[*/0x0296/*::]*/: { n:"??" },
/*::[*/0x0299/*::]*/: { n:"??" },
/*::[*/0x029A/*::]*/: { n:"??" },
/*::[*/0x0300/*::]*/: { n:"??" },
/*::[*/0x0304/*::]*/: { n:"??" },
/*::[*/0x0601/*::]*/: { n:"SHEETINFOQP", f:parse_SHEETINFOQP },
/*::[*/0x0640/*::]*/: { n:"??" },
/*::[*/0x0642/*::]*/: { n:"??" },
/*::[*/0x0701/*::]*/: { n:"??" },
/*::[*/0x0702/*::]*/: { n:"??" },
/*::[*/0x0703/*::]*/: { n:"??" },
/*::[*/0x0704/*::]*/: { n:"??" },
/*::[*/0x0780/*::]*/: { n:"??" },
/*::[*/0x0800/*::]*/: { n:"??" },
/*::[*/0x0801/*::]*/: { n:"??" },
/*::[*/0x0804/*::]*/: { n:"??" },
/*::[*/0x0A80/*::]*/: { n:"??" },
/*::[*/0x2AF6/*::]*/: { n:"??" },
/*::[*/0x3231/*::]*/: { n:"??" },
/*::[*/0x6E49/*::]*/: { n:"??" },
/*::[*/0x6F44/*::]*/: { n:"??" },
/*::[*/0xFFFF/*::]*/: { n:"" }
0x0000: { n:"BOF" },
0x0001: { n:"EOF" },
0x0002: { n:"PASSWORD" },
0x0003: { n:"CALCSET" },
0x0004: { n:"WINDOWSET" },
0x0005: { n:"SHEETCELLPTR" },
0x0006: { n:"SHEETLAYOUT" },
0x0007: { n:"COLUMNWIDTH" },
0x0008: { n:"HIDDENCOLUMN" },
0x0009: { n:"USERRANGE" },
0x000A: { n:"SYSTEMRANGE" },
0x000B: { n:"ZEROFORCE" },
0x000C: { n:"SORTKEYDIR" },
0x000D: { n:"FILESEAL" },
0x000E: { n:"DATAFILLNUMS" },
0x000F: { n:"PRINTMAIN" },
0x0010: { n:"PRINTSTRING" },
0x0011: { n:"GRAPHMAIN" },
0x0012: { n:"GRAPHSTRING" },
0x0013: { n:"??" },
0x0014: { n:"ERRCELL" },
0x0015: { n:"NACELL" },
0x0016: { n:"LABEL16", f:parse_LABEL_16},
0x0017: { n:"NUMBER17", f:parse_NUMBER_17 },
0x0018: { n:"NUMBER18", f:parse_NUMBER_18 },
0x0019: { n:"FORMULA19", f:parse_FORMULA_19},
0x001A: { n:"FORMULA1A" },
0x001B: { n:"XFORMAT", f:parse_XFORMAT },
0x001C: { n:"DTLABELMISC" },
0x001D: { n:"DTLABELCELL" },
0x001E: { n:"GRAPHWINDOW" },
0x001F: { n:"CPA" },
0x0020: { n:"LPLAUTO" },
0x0021: { n:"QUERY" },
0x0022: { n:"HIDDENSHEET" },
0x0023: { n:"??" },
0x0025: { n:"NUMBER25", f:parse_NUMBER_25 },
0x0026: { n:"??" },
0x0027: { n:"NUMBER27", f:parse_NUMBER_27 },
0x0028: { n:"FORMULA28", f:parse_FORMULA_28 },
0x008E: { n:"??" },
0x0093: { n:"??" },
0x0096: { n:"??" },
0x0097: { n:"??" },
0x0098: { n:"??" },
0x0099: { n:"??" },
0x009A: { n:"??" },
0x009B: { n:"??" },
0x009C: { n:"??" },
0x00A3: { n:"??" },
0x00AE: { n:"??" },
0x00AF: { n:"??" },
0x00B0: { n:"??" },
0x00B1: { n:"??" },
0x00B8: { n:"??" },
0x00B9: { n:"??" },
0x00BA: { n:"??" },
0x00BB: { n:"??" },
0x00BC: { n:"??" },
0x00C3: { n:"??" },
0x00C9: { n:"??" },
0x00CC: { n:"SHEETNAMECS", f:parse_SHEETNAMECS },
0x00CD: { n:"??" },
0x00CE: { n:"??" },
0x00CF: { n:"??" },
0x00D0: { n:"??" },
0x0100: { n:"??" },
0x0103: { n:"??" },
0x0104: { n:"??" },
0x0105: { n:"??" },
0x0106: { n:"??" },
0x0107: { n:"??" },
0x0109: { n:"??" },
0x010A: { n:"??" },
0x010B: { n:"??" },
0x010C: { n:"??" },
0x010E: { n:"??" },
0x010F: { n:"??" },
0x0180: { n:"??" },
0x0185: { n:"??" },
0x0186: { n:"??" },
0x0189: { n:"??" },
0x018C: { n:"??" },
0x0200: { n:"??" },
0x0202: { n:"??" },
0x0201: { n:"??" },
0x0204: { n:"??" },
0x0205: { n:"??" },
0x0280: { n:"??" },
0x0281: { n:"??" },
0x0282: { n:"??" },
0x0283: { n:"??" },
0x0284: { n:"??" },
0x0285: { n:"??" },
0x0286: { n:"??" },
0x0287: { n:"??" },
0x0288: { n:"??" },
0x0292: { n:"??" },
0x0293: { n:"??" },
0x0294: { n:"??" },
0x0295: { n:"??" },
0x0296: { n:"??" },
0x0299: { n:"??" },
0x029A: { n:"??" },
0x0300: { n:"??" },
0x0304: { n:"??" },
0x0601: { n:"SHEETINFOQP", f:parse_SHEETINFOQP },
0x0640: { n:"??" },
0x0642: { n:"??" },
0x0701: { n:"??" },
0x0702: { n:"??" },
0x0703: { n:"??" },
0x0704: { n:"??" },
0x0780: { n:"??" },
0x0800: { n:"??" },
0x0801: { n:"??" },
0x0804: { n:"??" },
0x0A80: { n:"??" },
0x2AF6: { n:"??" },
0x3231: { n:"??" },
0x6E49: { n:"??" },
0x6F44: { n:"??" },
0xFFFF: { n:"" }
};
/* TODO: fill out and verify this table across QP versions */
var QPWNFTable = {
0x05: "dd-mmm-yy",
0x06: "dd-mmm",
0x07: "mmm-yy",
0x08: "mm/dd/yy", // Long Date Intl
0x0A: "hh:mm:ss AM/PM",
0x0B: "hh:mm AM/PM",
0x0E: "dd-mmm-yyyy",
0x0F: "mmm-yyyy",
/* It is suspected that the the low nybble specifies decimal places */
0x0022: "0.00",
0x0032: "0.00;[Red]0.00",
0x0042: "0.00;\(0.00\)",
0x0052: "0.00;[Red]\(0.00\)",
0x00A2: '"$"#,##0.00;\\("$"#,##0.00\\)',
0x0120: '0%',
0x0130: '0E+00',
0x0140: '# ?/?'
};
function parse_qpw_str(p) {
var cch = p.read_shift(2);
var flags = p.read_shift(1);
/* TODO: find examples with nonzero flags */
if(flags != 0) throw "unsupported QPW string type " + flags.toString(16);
return p.read_shift(cch, "sbcs-cont");
}
/* QPW uses a different set of record types */
function qpw_to_workbook_buf(d, opts)/*:Workbook*/ {
prep_blob(d, 0);
var o = opts || {};
if(DENSE != null && o.dense == null) o.dense = DENSE;
var s/*:Worksheet*/ = ((o.dense ? [] : {})/*:any*/);
var s/*:Worksheet*/ = ({}/*:any*/); if(o.dense) s["!data"] = [];
var SST = [], sname = "", formulae = [];
var range = {s:{r:-1,c:-1}, e:{r:-1,c:-1}};
var cnt = 0, type = 0, C = 0, R = 0;
var wb = { SheetNames: [], Sheets: {} };
var FMTS = [];
outer: while(d.l < d.length) {
var RT = d.read_shift(2), length = d.read_shift(2);
var p = d.slice(d.l, d.l + length);
@ -934,6 +1017,22 @@ var WK_ = /*#__PURE__*/(function() {
break;
case 0x02: /* EOF */ break outer;
case 0x08: /* NF */ break; // TODO: this is tied to custom number formats
case 0x0A: /* FORMATS */ {
var fcnt = p.read_shift(4);
var step = ((p.length - p.l)/ fcnt)|0;
for(var ifmt = 0; ifmt < fcnt; ++ifmt) {
var end = p.l + step;
var fmt = {};
p.l += 2;
fmt.numFmtId = p.read_shift(2);
if(QPWNFTable[fmt.numFmtId]) fmt.z = QPWNFTable[fmt.numFmtId];
p.l = end;
FMTS.push(fmt);
}
} break;
/* TODO: The behavior here should be consistent with Numbers: QP Notebook ~ .TN.SheetArchive, QP Sheet ~ .TST.TableModelArchive */
case 0x0401: /* BON */ break;
case 0x0402: /* EON */ /* TODO: backfill missing sheets based on BON cnt */ break;
@ -956,7 +1055,7 @@ var WK_ = /*#__PURE__*/(function() {
case 0x0601: { /* BOS */
var sidx = p.read_shift(2);
s = ((o.dense ? [] : {})/*:any*/);
s = ({}/*:any*/); if(o.dense) s["!data"] = [];
range.s.c = p.read_shift(2);
range.e.c = p.read_shift(2);
range.s.r = p.read_shift(4);
@ -993,20 +1092,28 @@ var WK_ = /*#__PURE__*/(function() {
R = p.read_shift(4), cnt = p.read_shift(4);
if(range.s.r > R) range.s.r = R;
if(range.e.r < R + cnt - 1) range.e.r = R + cnt - 1;
var CC = encode_col(C);
while(p.l < p.length) {
var cell = { t: "z" };
var flags = p.read_shift(1);
if(flags & 0x80) p.l += 2;
var flags = p.read_shift(1), fmtidx = -1;
if(flags & 0x80) fmtidx = p.read_shift(2);
var mul = (flags & 0x40) ? p.read_shift(2) - 1: 0;
switch(flags & 0x1F) {
case 0: break;
case 1: break;
case 2: cell = { t: "n", v: p.read_shift(2) }; break;
case 3: cell = { t: "n", v: p.read_shift(2, 'i') }; break;
case 4: cell = { t: "n", v: parse_RkNumber(p) }; break;
case 5: cell = { t: "n", v: p.read_shift(8, 'f') }; break;
case 7: cell = { t: "s", v: SST[type = p.read_shift(4) - 1] }; break;
case 8: cell = { t: "n", v: p.read_shift(8, 'f') }; p.l += 2; /* cell.f = formulae[p.read_shift(4)]; */ p.l += 4; break;
case 8:
cell = { t: "n", v: p.read_shift(8, 'f') };
p.l += 2; /* cell.f = formulae[p.read_shift(4)]; */ p.l += 4;
if(isNaN(cell.v)) cell = { t: "e", v: 0x0F }; // #VALUE!
break;
default: throw "Unrecognized QPW cell type " + (flags & 0x1F);
}
if(fmtidx != -1 && (FMTS[fmtidx - 1]||{}).z) cell.z = FMTS[fmtidx-1].z;
var delta = 0;
if(flags & 0x20) switch(flags & 0x1F) {
case 2: delta = p.read_shift(2); break;
@ -1015,10 +1122,14 @@ var WK_ = /*#__PURE__*/(function() {
default: throw "Unsupported delta for QPW cell type " + (flags & 0x1F);
}
if(!(!o.sheetStubs && cell.t == "z")) {
if(Array.isArray(s)) {
if(!s[R]) s[R] = [];
s[R][C] = cell;
} else s[encode_cell({r:R, c:C})] = cell;
var newcell = dup(cell);
if(cell.t == "n" && cell.z && fmt_is_date(cell.z) && o.cellDates) {
newcell.v = numdate(cell.v); newcell.t = typeof newcell.v == "number" ? 'n' : 'd';
}
if(s["!data"] != null) {
if(!s["!data"][R]) s["!data"][R] = [];
s["!data"][R][C] = newcell;
} else s[CC + encode_row(R)] = newcell;
}
++R; --cnt;
while(mul-- > 0 && cnt >= 0) {
@ -1033,17 +1144,29 @@ var WK_ = /*#__PURE__*/(function() {
case 7: cell = { t: "s", v: SST[type = p.read_shift(4) - 1] }; break;
default: throw "Cannot apply repeat for QPW cell type " + (flags & 0x1F);
}
if(fmtidx != -1);
if(!(!o.sheetStubs && cell.t == "z")) {
if(Array.isArray(s)) {
if(!s[R]) s[R] = [];
s[R][C] = cell;
} else s[encode_cell({r:R, c:C})] = cell;
if(s["!data"] != null) {
if(!s["!data"][R]) s["!data"][R] = [];
s["!data"][R][C] = cell;
} else s[CC + encode_row(R)] = cell;
}
++R; --cnt;
}
}
} break;
case 0x0C02: { /* String (result of string formula expression) */
C = p.read_shift(2);
R = p.read_shift(4);
var str = parse_qpw_str(p);
/* TODO: QP10 record has an additional unknown character after the string */
if(s["!data"] != null) {
if(!s["!data"][R]) s["!data"][R] = [];
s["!data"][R][C] = { t:"s", v:str };
} else s[encode_col(C) + encode_row(R)] = { t:"s", v:str };
} break;
default: break;
}
d.l += length;

@ -4,7 +4,7 @@ function parse_rpr(rpr) {
var pass = false;
if(m) for(;i!=m.length; ++i) {
var y = parsexmltag(m[i]);
switch(y[0].replace(/\w*:/g,"")) {
switch(y[0].replace(/<\w*:/g,"<")) {
/* 18.8.12 condense CT_BooleanProperty */
/* ** not required . */
case '<condense': break;
@ -107,15 +107,14 @@ function parse_rpr(rpr) {
}
var parse_rs = /*#__PURE__*/(function() {
var tregex = matchtag("t"), rpregex = matchtag("rPr");
/* 18.4.4 r CT_RElt */
function parse_r(r) {
/* 18.4.12 t ST_Xstring */
var t = r.match(tregex)/*, cp = 65001*/;
var t = str_match_xml_ns(r, "t")/*, cp = 65001*/;
if(!t) return {t:"s", v:""};
var o/*:Cell*/ = ({t:'s', v:unescapexml(t[1])}/*:any*/);
var rpr = r.match(rpregex);
var rpr = str_match_xml_ns(r, "rPr");
if(rpr) o.s = parse_rpr(rpr[1]);
return o;
}
@ -168,8 +167,7 @@ var rs_to_html = /*#__PURE__*/(function parse_rs_factory() {
})();
/* 18.4.8 si CT_Rst */
var sitregex = /<(?:\w+:)?t[^>]*>([^<]*)<\/(?:\w+:)?t>/g, sirregex = /<(?:\w+:)?r>/;
var sirphregex = /<(?:\w+:)?rPh.*?>([\s\S]*?)<\/(?:\w+:)?rPh>/g;
var sitregex = /<(?:\w+:)?t\b[^<>]*>([^<]*)<\/(?:\w+:)?t>/g, sirregex = /<(?:\w+:)?r\b[^<>]*>/;
function parse_si(x, opts) {
var html = opts ? opts.cellHTML : true;
var z = {};
@ -185,7 +183,7 @@ function parse_si(x, opts) {
/* 18.4.4 r CT_RElt (Rich Text Run) */
else if((/*y = */x.match(sirregex))) {
z.r = utf8read(x);
z.t = unescapexml(utf8read((x.replace(sirphregex, '').match(sitregex)||[]).join("").replace(tagregex,"")), true);
z.t = unescapexml(utf8read((str_remove_xml_ns_g(x, "rPh").match(sitregex)||[]).join("").replace(tagregex,"")), true);
if(html) z.h = rs_to_html(parse_rs(z.r));
}
/* 18.4.3 phoneticPr CT_PhoneticPr (TODO: needed for Asian support) */
@ -194,21 +192,20 @@ function parse_si(x, opts) {
}
/* 18.4 Shared String Table */
var sstr0 = /<(?:\w+:)?sst([^>]*)>([\s\S]*)<\/(?:\w+:)?sst>/;
var sstr1 = /<(?:\w+:)?(?:si|sstItem)>/g;
var sstr2 = /<\/(?:\w+:)?(?:si|sstItem)>/;
function parse_sst_xml(data/*:string*/, opts)/*:SST*/ {
var s/*:SST*/ = ([]/*:any*/), ss = "";
if(!data) return s;
/* 18.4.9 sst CT_Sst */
var sst = data.match(sstr0);
var sst = str_match_xml_ns(data, "sst");
if(sst) {
ss = sst[2].replace(sstr1,"").split(sstr2);
ss = sst[1].replace(sstr1,"").split(sstr2);
for(var i = 0; i != ss.length; ++i) {
var o = parse_si(ss[i].trim(), opts);
if(o != null) s[s.length] = o;
}
sst = parsexmltag(sst[1]); s.Count = sst.count; s.Unique = sst.uniqueCount;
sst = parsexmltag(sst[0].slice(0, sst[0].indexOf(">"))); s.Count = sst.count; s.Unique = sst.uniqueCount;
}
return s;
}
@ -229,6 +226,7 @@ function write_sst_xml(sst/*:SST*/, opts)/*:string*/ {
else {
sitag += "<t";
if(!s.t) s.t = "";
if(typeof s.t !== "string") s.t = String(s.t);
if(s.t.match(straywsregex)) sitag += ' xml:space="preserve"';
sitag += ">" + escapexml(s.t) + "</t>";
}

@ -13,14 +13,18 @@ function rtf_to_sheet(d, opts) {
}
function rtf_to_sheet_str(str, opts) {
var o = opts || {};
var ws = o.dense ? [] : {};
var rows = str.match(/\\trowd[\s\S]*?\\row\b/g);
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 (Array.isArray(ws))
ws[R] = [];
if (dense)
row = ws["!data"][R] = [];
var rtfre = /\\[\w\-]+\b/g;
var last_index = 0;
var res;
@ -45,9 +49,13 @@ function rtf_to_sheet_str(str, opts) {
if (o.cellText !== false)
cell.w = cell.v;
cell.v = fuzzynum(cell.v);
} else if (RBErr[cell.v] != null) {
cell.t = "e";
cell.w = cell.v;
cell.v = RBErr[cell.v];
}
if (Array.isArray(ws))
ws[R][C] = cell;
if (dense)
row[C] = cell;
else
ws[encode_cell({ r: R, c: C })] = cell;
}
@ -75,15 +83,17 @@ function sheet_to_rtf(ws, opts) {
if (!ws["!ref"])
return o[0] + "}";
var r = safe_decode_range(ws["!ref"]), cell;
var dense = Array.isArray(ws);
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 ? (ws[R] || [])[C] : ws[coord];
cell = dense ? row[C] : ws[coord];
if (!cell || cell.v == null && (!cell.f || cell.F)) {
o.push(" \\cell");
continue;

@ -3,7 +3,7 @@ function parse_borders(t, styles, themes, opts) {
styles.Borders = [];
var border = {};
var pass = false;
(t[0].match(tagregex)||[]).forEach(function(x) {
(t.match(tagregex)||[]).forEach(function(x) {
var y = parsexmltag(x);
switch(strip_ns(y[0])) {
case '<borders': case '<borders>': case '</borders>': break;
@ -78,7 +78,7 @@ function parse_fills(t, styles, themes, opts) {
styles.Fills = [];
var fill = {};
var pass = false;
(t[0].match(tagregex)||[]).forEach(function(x) {
(t.match(tagregex)||[]).forEach(function(x) {
var y = parsexmltag(x);
switch(strip_ns(y[0])) {
case '<fills': case '<fills>': case '</fills>': break;
@ -144,7 +144,7 @@ function parse_fonts(t, styles, themes, opts) {
styles.Fonts = [];
var font = {};
var pass = false;
(t[0].match(tagregex)||[]).forEach(function(x) {
(t.match(tagregex)||[]).forEach(function(x) {
var y = parsexmltag(x);
switch(strip_ns(y[0])) {
case '<fonts': case '<fonts>': case '</fonts>': break;
@ -163,10 +163,12 @@ function parse_fonts(t, styles, themes, opts) {
/* 18.8.2 b CT_BooleanProperty */
case '<b': font.bold = y.val ? parsexmlbool(y.val) : 1; break;
case '<b/>': font.bold = 1; break;
case '</b>': case '</b': break;
/* 18.8.26 i CT_BooleanProperty */
case '<i': font.italic = y.val ? parsexmlbool(y.val) : 1; break;
case '<i/>': font.italic = 1; break;
case '</i>': case '</i': break;
/* 18.4.13 u CT_UnderlineProperty */
case '<u':
@ -178,48 +180,55 @@ function parse_fonts(t, styles, themes, opts) {
case "doubleAccounting": font.underline = 0x22; break;
} break;
case '<u/>': font.underline = 1; break;
case '</u>': case '</u': break;
/* 18.4.10 strike CT_BooleanProperty */
case '<strike': font.strike = y.val ? parsexmlbool(y.val) : 1; break;
case '<strike/>': font.strike = 1; break;
case '</strike>': case '</strike': break;
/* 18.4.2 outline CT_BooleanProperty */
case '<outline': font.outline = y.val ? parsexmlbool(y.val) : 1; break;
case '<outline/>': font.outline = 1; break;
case '</outline>': case '</outline': break;
/* 18.8.36 shadow CT_BooleanProperty */
case '<shadow': font.shadow = y.val ? parsexmlbool(y.val) : 1; break;
case '<shadow/>': font.shadow = 1; break;
case '</shadow>': case '</shadow': break;
/* 18.8.12 condense CT_BooleanProperty */
case '<condense': font.condense = y.val ? parsexmlbool(y.val) : 1; break;
case '<condense/>': font.condense = 1; break;
case '</condense>': case '</condense': break;
/* 18.8.17 extend CT_BooleanProperty */
case '<extend': font.extend = y.val ? parsexmlbool(y.val) : 1; break;
case '<extend/>': font.extend = 1; break;
case '</extend>': case '</extend': break;
/* 18.4.11 sz CT_FontSize */
case '<sz': if(y.val) font.sz = +y.val; break;
case '<sz/>': case '</sz>': break;
case '<sz/>': 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;
case '<vertAlign/>': 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;
case '<family/>': 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;
case '<scheme/>': 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;
case '<charset/>': case '</charset>': case '</charset': break;
/* 18.?.? color CT_Color */
case '<color':
@ -242,11 +251,11 @@ function parse_fonts(t, styles, themes, opts) {
}
break;
case '<color/>': case '</color>': break;
case '<color/>': case '</color>': case '</color': break;
/* note: sometimes mc:AlternateContent appears bare */
case '<AlternateContent': pass = true; break;
case '</AlternateContent>': pass = false; break;
case '</AlternateContent>': case '</AlternateContent': pass = false; break;
/* 18.2.10 extLst CT_ExtensionList ? */
case '<extLst': case '<extLst>': case '</extLst>': break;
@ -264,7 +273,7 @@ function parse_numFmts(t, styles, opts) {
styles.NumberFmt = [];
var k/*Array<number>*/ = (keys(table_fmt)/*:any*/);
for(var i=0; i < k.length; ++i) styles.NumberFmt[k[i]] = table_fmt[k[i]];
var m = t[0].match(tagregex);
var m = t.match(tagregex);
if(!m) return;
for(i=0; i < m.length; ++i) {
var y = parsexmltag(m[i]);
@ -305,13 +314,13 @@ function parse_cellXfs(t, styles, opts) {
styles.CellXf = [];
var xf;
var pass = false;
(t[0].match(tagregex)||[]).forEach(function(x) {
(t.match(tagregex)||[]).forEach(function(x) {
var y = parsexmltag(x), i = 0;
switch(strip_ns(y[0])) {
case '<cellXfs': case '<cellXfs>': case '<cellXfs/>': case '</cellXfs>': break;
/* 18.8.45 xf CT_Xf */
case '<xf': case '<xf/>':
case '<xf': case '<xf/>': case '<xf>':
xf = y;
delete xf[0];
for(i = 0; i < cellXF_uint.length; ++i) if(xf[cellXF_uint[i]])
@ -325,7 +334,7 @@ function parse_cellXfs(t, styles, opts) {
case '</xf>': break;
/* 18.8.1 alignment CT_CellAlignment */
case '<alignment': case '<alignment/>':
case '<alignment': case '<alignment/>': case '<alignment>':
var alignment = {};
if(y.vertical) alignment.vertical = y.vertical;
if(y.horizontal) alignment.horizontal = y.horizontal;
@ -337,12 +346,12 @@ function parse_cellXfs(t, styles, opts) {
case '</alignment>': break;
/* 18.8.33 protection CT_CellProtection */
case '<protection':
case '<protection': case '<protection>':
break;
case '</protection>': case '<protection/>': break;
/* note: sometimes mc:AlternateContent appears bare */
case '<AlternateContent': pass = true; break;
case '<AlternateContent': case '<AlternateContent>': pass = true; break;
case '</AlternateContent>': pass = false; break;
/* 18.2.10 extLst CT_ExtensionList ? */
@ -370,36 +379,31 @@ function write_cellXfs(cellXfs)/*:string*/ {
/* 18.8 Styles CT_Stylesheet*/
var parse_sty_xml= /*#__PURE__*/(function make_pstyx() {
var numFmtRegex = /<(?:\w+:)?numFmts([^>]*)>[\S\s]*?<\/(?:\w+:)?numFmts>/;
var cellXfRegex = /<(?:\w+:)?cellXfs([^>]*)>[\S\s]*?<\/(?:\w+:)?cellXfs>/;
var fillsRegex = /<(?:\w+:)?fills([^>]*)>[\S\s]*?<\/(?:\w+:)?fills>/;
var fontsRegex = /<(?:\w+:)?fonts([^>]*)>[\S\s]*?<\/(?:\w+:)?fonts>/;
var bordersRegex = /<(?:\w+:)?borders([^>]*)>[\S\s]*?<\/(?:\w+:)?borders>/;
return function parse_sty_xml(data, themes, opts) {
var styles = {};
if(!data) return styles;
data = data.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
data = remove_doctype(str_remove_ng(data, "<!--", "-->"));
/* 18.8.39 styleSheet CT_Stylesheet */
var t;
/* 18.8.31 numFmts CT_NumFmts ? */
if((t=data.match(numFmtRegex))) parse_numFmts(t, styles, opts);
if((t=str_match_xml_ns(data, "numFmts"))) parse_numFmts(t[0], styles, opts);
/* 18.8.23 fonts CT_Fonts ? */
if((t=data.match(fontsRegex))) parse_fonts(t, styles, themes, opts);
if((t=str_match_xml_ns(data, "fonts"))) parse_fonts(t[0], styles, themes, opts);
/* 18.8.21 fills CT_Fills ? */
if((t=data.match(fillsRegex))) parse_fills(t, styles, themes, opts);
if((t=str_match_xml_ns(data, "fills"))) parse_fills(t[0], styles, themes, opts);
/* 18.8.5 borders CT_Borders ? */
if((t=data.match(bordersRegex))) parse_borders(t, styles, themes, opts);
if((t=str_match_xml_ns(data, "borders"))) parse_borders(t[0], styles, themes, opts);
/* 18.8.9 cellStyleXfs CT_CellStyleXfs ? */
/* 18.8.8 cellStyles CT_CellStyles ? */
/* 18.8.10 cellXfs CT_CellXfs ? */
if((t=data.match(cellXfRegex))) parse_cellXfs(t, styles, opts);
if((t=str_match_xml_ns(data, "cellXfs"))) parse_cellXfs(t[0], styles, opts);
/* 18.8.15 dxfs CT_Dxfs ? */
/* 18.8.42 tableStyles CT_TableStyles ? */

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

@ -71,7 +71,7 @@ function parse_xlmeta_xml(data, name, opts) {
lastmeta.offsets.push(+y.i);
break;
default:
if (!pass && opts.WTF)
if (!pass && (opts == null ? void 0 : opts.WTF))
throw new Error("unrecognized " + y[0] + " in metadata");
}
return x;

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

@ -1,5 +1,42 @@
/* L.5.5.2 SpreadsheetML Comments + VML Schema */
function write_vml(rId/*:number*/, comments) {
function parse_vml(data/*:string*/, sheet, comments) {
var cidx = 0;
(str_match_xml_ns_g(data, "shape")||[]).forEach(function(m) {
var type = "";
var hidden = true;
var aidx = -1;
var R = -1, C = -1;
m.replace(tagregex, function(x/*:string*/, idx/*:number*/) {
var y = parsexmltag(x);
switch(strip_ns(y[0])) {
case '<ClientData': if(y.ObjectType) type = y.ObjectType; break;
case '<Visible': case '<Visible/>': hidden = false; break;
case '<Row': case '<Row>': aidx = idx + x.length; break;
case '</Row>': R = +m.slice(aidx, idx).trim(); break;
case '<Column': case '<Column>': aidx = idx + x.length; break;
case '</Column>': C = +m.slice(aidx, idx).trim(); break;
}
return "";
});
switch(type) {
case 'Note':
var cell = ws_get_cell_stub(sheet, ((R>=0 && C>=0) ? encode_cell({r:R,c:C}) : comments[cidx].ref));
if(cell.c) {
cell.c.hidden = hidden;
}
++cidx;
break;
}
});
}
/* comment boxes */
function write_vml(rId/*:number*/, comments, ws) {
var csize = [21600, 21600];
/* L.5.2.1.2 Path Attribute */
var bbox = ["m0,0l0",csize[1],csize[0],csize[1],csize[0],"0xe"].join(",");
@ -21,7 +58,7 @@ function write_vml(rId/*:number*/, comments) {
return o.join("");
}
function write_vml_comment(x, _shapeid)/*:string*/ {
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";

@ -1,15 +1,16 @@
function sheet_insert_comments(sheet, comments/*:Array<RawComment>*/, threaded/*:boolean*/, people/*:?Array<any>*/) {
var dense = Array.isArray(sheet);
function sheet_insert_comments(sheet/*:WorkSheet*/, comments/*:Array<RawComment>*/, threaded/*:boolean*/, people/*:?Array<any>*/) {
var dense = sheet["!data"] != null;
var cell/*:Cell*/;
comments.forEach(function(comment) {
var r = decode_cell(comment.ref);
if(r.r < 0 || r.c < 0) return;
if(dense) {
if(!sheet[r.r]) sheet[r.r] = [];
cell = sheet[r.r][r.c];
if(!sheet["!data"][r.r]) sheet["!data"][r.r] = [];
cell = sheet["!data"][r.r][r.c];
} else cell = sheet[comment.ref];
if (!cell) {
cell = ({t:"z"}/*:any*/);
if(dense) sheet[r.r][r.c] = cell;
if(dense) sheet["!data"][r.r][r.c] = cell;
else sheet[comment.ref] = cell;
var range = safe_decode_range(sheet["!ref"]||"BDWGO1000001:A1");
if(range.s.r > r.r) range.s.r = r.r;
@ -17,7 +18,7 @@ function sheet_insert_comments(sheet, comments/*:Array<RawComment>*/, threaded/*
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 = [];
@ -35,4 +36,3 @@ function sheet_insert_comments(sheet, comments/*:Array<RawComment>*/, threaded/*
cell.c.push(o);
});
}

@ -4,22 +4,22 @@ function parse_comments_xml(data/*:string*/, opts)/*:Array<RawComment>*/ {
if(data.match(/<(?:\w+:)?comments *\/>/)) return [];
var authors/*:Array<string>*/ = [];
var commentList/*:Array<RawComment>*/ = [];
var authtag = data.match(/<(?:\w+:)?authors>([\s\S]*)<\/(?:\w+:)?authors>/);
var authtag = str_match_xml_ns(data, "authors");
if(authtag && authtag[1]) authtag[1].split(/<\/\w*:?author>/).forEach(function(x) {
if(x === "" || x.trim() === "") return;
var a = x.match(/<(?:\w+:)?author[^>]*>(.*)/);
var a = x.match(/<(?:\w+:)?author[^<>]*>(.*)/);
if(a) authors.push(a[1]);
});
var cmnttag = data.match(/<(?:\w+:)?commentList>([\s\S]*)<\/(?:\w+:)?commentList>/);
var cmnttag = str_match_xml_ns(data, "commentList");
if(cmnttag && cmnttag[1]) cmnttag[1].split(/<\/\w*:?comment>/).forEach(function(x) {
if(x === "" || x.trim() === "") return;
var cm = x.match(/<(?:\w+:)?comment[^>]*>/);
var cm = x.match(/<(?:\w+:)?comment[^<>]*>/);
if(!cm) return;
var y = parsexmltag(cm[0]);
var comment/*:RawComment*/ = ({ author: y.authorId && authors[y.authorId] || "sheetjsghost", ref: y.ref, guid: y.guid }/*:any*/);
var cell = decode_cell(y.ref);
if(opts.sheetRows && opts.sheetRows <= cell.r) return;
var textMatch = x.match(/<(?:\w+:)?text>([\s\S]*)<\/(?:\w+:)?text>/);
var textMatch = str_match_xml_ns(x, "text");
var rt = !!textMatch && !!textMatch[1] && parse_si(textMatch[1]) || {r:"",t:"",h:""};
comment.r = rt.r;
if(rt.r == "<t></t>") rt.t = rt.h = "";
@ -50,21 +50,28 @@ function write_comments_xml(data/*::, opts*/) {
o.push("<commentList>");
data.forEach(function(d) {
/* 18.7.3 CT_Comment */
var lastauthor = 0, ts = [];
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);
else d[1].forEach(function(c) {
d[1].forEach(function(c) {
if(c.a) lastauthor = iauthor.indexOf(escapexml(c.a));
ts.push(c.t||"");
if(c.T) ++tcnt;
ts.push(c.t == null ? "" : escapexml(c.t));
});
o.push('<comment ref="' + d[0] + '" authorId="' + lastauthor + '"><text>');
if(ts.length <= 1) o.push(writetag("t", escapexml(ts[0]||"")));
else {
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('</text></comment>');
});
o.push("</commentList>");
if(o.length>2) { o[o.length] = ('</comments>'); o[1]=o[1].replace("/>",">"); }

@ -74,6 +74,10 @@ function write_comments_bin(data/*::, opts*/) {
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 */);
@ -81,7 +85,11 @@ function write_comments_bin(data/*::, opts*/) {
write_record(ba, 0x0279 /* BrtBeginCommentList */);
data.forEach(function(comment) {
comment[1].forEach(function(c) {
c.iauthor = iauthor.indexOf(c.a);
var _ia = -1;
if(c.ID) _ia = iauthor.indexOf("tc=" + c.ID);
if(_ia == -1 && comment[1][0].T && comment[1][0].ID) _ia = iauthor.indexOf("tc=" + comment[1][0].ID);
if(_ia == -1) _ia = iauthor.indexOf(c.a);
c.iauthor = _ia;
var range = {s:decode_cell(comment[0]),e:decode_cell(comment[0])};
write_record(ba, 0x027B /* BrtBeginComment */, write_BrtBeginComment([range, c]));
if(c.t && c.t.length > 0) write_record(ba, 0x027D /* BrtCommentText */, write_BrtCommentText(c));

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

@ -23,7 +23,10 @@ var rc_to_a1 = /*#__PURE__*/(function(){
};
})();
var crefregex = /(^|[^._A-Z0-9])([$]?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])([$]?)(10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})(?![_.\(A-Za-z0-9])/g;
var 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) {

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

@ -68,8 +68,7 @@ function write_FormulaValue(value) {
/* [MS-XLS] 2.4.127 TODO */
function parse_Formula(blob, length, opts) {
var end = blob.l + length;
var cell = parse_XLSCell(blob, 6);
if(opts.biff == 2) ++blob.l;
var cell = parse_XLSCell(blob, 6, opts);
var val = parse_FormulaValue(blob,8);
var flags = blob.read_shift(1);
if(opts.biff != 2) {
@ -263,7 +262,7 @@ function write_XLSBFormulaRangeWS(_str, wb) {
var sname = _str.slice(0, lastbang);
_str = _str.slice(lastbang+1);
if(sname.charAt(0) == "'") sname = sname.slice(1, -1).replace(/''/g, "'");
var parts = _str.split(":"); str = parts[0];
var parts = _str.split(":");
var out = new_buf(27);
out.write_shift(4, 19);

@ -31,6 +31,6 @@ function ods_to_csf_3D(r/*:string*/)/*:[string, string]*/ {
}
function csf_to_ods_3D(r/*:string*/)/*:string*/ {
return r.replace(/!/,".");
return r.replace(/!/,".").replace(/:/, ":.");
}

@ -81,7 +81,7 @@ function get_cell_style(styles/*:Array<any>*/, cell/*:Cell*/, opts) {
return len;
}
function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, themes, styles) {
function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, themes, styles, date1904) {
try {
if(opts.cellNF) p.z = table_fmt[fmtid];
} catch(e) { if(opts.WTF) throw e; }
@ -96,14 +96,14 @@ function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, the
else p.w = SSF_general_num(p.v);
}
else if(p.t === 'd') {
var dd = datenum(p.v);
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 if(p.t === 'd') p.w = SSF_format(fmtid,datenum(p.v),_ssfopts);
else if(p.t === 'd') p.w = SSF_format(fmtid,datenum(p.v, !!date1904),_ssfopts);
else p.w = SSF_format(fmtid,p.v,_ssfopts);
} catch(e) { if(opts.WTF) throw e; }
if(!opts.cellStyles) return;

@ -2,16 +2,13 @@ function parse_ws_xml_dim(ws/*:Worksheet*/, s/*:string*/) {
var d = safe_decode_range(s);
if(d.s.r<=d.e.r && d.s.c<=d.e.c && d.s.r>=0 && d.s.c>=0) ws["!ref"] = encode_range(d);
}
var mergecregex = /<(?:\w:)?mergeCell ref="[A-Z0-9:]+"\s*[\/]?>/g;
var sheetdataregex = /<(?:\w+:)?sheetData[^>]*>([\s\S]*)<\/(?:\w+:)?sheetData>/;
var hlinkregex = /<(?:\w:)?hyperlink [^>]*>/mg;
var mergecregex = /<(?:\w+:)?mergeCell ref=["'][A-Z0-9:]+['"]\s*[\/]?>/g;
var hlinkregex = /<(?:\w+:)?hyperlink [^<>]*>/mg;
var dimregex = /"(\w*:\w*)"/;
var colregex = /<(?:\w:)?col\b[^>]*[\/]?>/g;
var colregex = /<(?:\w+:)?col\b[^<>]*[\/]?>/g;
var afregex = /<(?:\w:)?autoFilter[^>]*([\/]|>([\s\S]*)<\/(?:\w:)?autoFilter)>/g;
var marginregex= /<(?:\w:)?pageMargins[^>]*\/>/g;
var sheetprregex = /<(?:\w:)?sheetPr\b(?:[^>a-z][^>]*)?\/>/;
var sheetprregex2= /<(?:\w:)?sheetPr[^>]*(?:[\/]|>([\s\S]*)<\/(?:\w:)?sheetPr)>/;
var svsregex = /<(?:\w:)?sheetViews[^>]*(?:[\/]|>([\s\S]*)<\/(?:\w:)?sheetViews)>/;
var marginregex= /<(?:\w+:)?pageMargins[^<>]*\/>/g;
var sheetprregex = /<(?:\w+:)?sheetPr\b[^<>]*?\/>/;
/* 18.3 Worksheets */
function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBProps*/, themes, styles)/*:Worksheet*/ {
@ -20,11 +17,11 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
if(DENSE != null && opts.dense == null) opts.dense = DENSE;
/* 18.3.1.99 worksheet CT_Worksheet */
var s = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
var s = ({}/*:any*/); if(opts.dense) s["!data"] = [];
var refguess/*:Range*/ = ({s: {r:2000000, c:2000000}, e: {r:0, c:0} }/*:any*/);
var data1 = "", data2 = "";
var mtch/*:?any*/ = data.match(sheetdataregex);
var mtch/*:?any*/ = str_match_xml_ns(data, "sheetData");
if(mtch) {
data1 = data.slice(0, mtch.index);
data2 = data.slice(mtch.index + mtch[0].length);
@ -33,17 +30,17 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
/* 18.3.1.82 sheetPr CT_SheetPr */
var sheetPr = data1.match(sheetprregex);
if(sheetPr) parse_ws_xml_sheetpr(sheetPr[0], s, wb, idx);
else if((sheetPr = data1.match(sheetprregex2))) parse_ws_xml_sheetpr2(sheetPr[0], sheetPr[1]||"", s, wb, idx, styles, themes);
else if((sheetPr = str_match_xml_ns(data1, "sheetPr"))) parse_ws_xml_sheetpr2(sheetPr[0], sheetPr[1]||"", s, wb, idx, styles, themes);
/* 18.3.1.35 dimension CT_SheetDimension */
var ridx = (data1.match(/<(?:\w*:)?dimension/)||{index:-1}).index;
if(ridx > 0) {
var ref = data1.slice(ridx,ridx+50).match(dimregex);
if(ref) parse_ws_xml_dim(s, ref[1]);
if(ref && !(opts && opts.nodim)) parse_ws_xml_dim(s, ref[1]);
}
/* 18.3.1.88 sheetViews CT_SheetViews */
var svs = data1.match(svsregex);
var svs = str_match_xml_ns(data1, "sheetViews");
if(svs && svs[1]) parse_ws_xml_sheetviews(svs[1], wb);
/* 18.3.1.17 cols CT_Cols */
@ -55,7 +52,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
}
/* 18.3.1.80 sheetData CT_SheetData ? */
if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles);
if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles, wb);
/* 18.3.1.2 autoFilter CT_AutoFilter */
var afilter = data2.match(afregex);
@ -65,7 +62,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
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));
merges[ridx] = safe_decode_range(_merge[ridx].slice(_merge[ridx].indexOf("=")+2));
/* 18.3.1.48 hyperlinks CT_Hyperlinks */
var hlink = data2.match(hlinkregex);
@ -75,6 +72,11 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
var margins = data2.match(marginregex);
if(margins) s['!margins'] = parse_ws_xml_margins(parsexmltag(margins[0]));
/* legacyDrawing */
var m;
if((m = data2.match(/legacyDrawing r:id="(.*?)"/))) s['!legrel'] = m[1];
if(opts && opts.nodim) refguess.s.c = refguess.s.r = 0;
if(!s["!ref"] && refguess.e.c >= refguess.s.c && refguess.e.r >= refguess.s.r) s["!ref"] = encode_range(refguess);
if(opts.sheetRows > 0 && s["!ref"]) {
var tmpref = safe_decode_range(s["!ref"]);
@ -90,6 +92,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
}
if(columns.length > 0) s["!cols"] = columns;
if(merges.length > 0) s["!merges"] = merges;
if(rels['!id'][s['!legrel']]) s['!legdrawel'] = rels['!id'][s['!legrel']];
return s;
}
@ -149,7 +152,7 @@ function write_ws_xml_protection(sp)/*:string*/ {
}
function parse_ws_xml_hlinks(s, data/*:Array<string>*/, rels) {
var dense = Array.isArray(s);
var dense = s["!data"] != null;
for(var i = 0; i != data.length; ++i) {
var val = parsexmltag(utf8read(data[i]), true);
if(!val.ref) return;
@ -165,11 +168,11 @@ function parse_ws_xml_hlinks(s, data/*:Array<string>*/, rels) {
if(val.tooltip) { val.Tooltip = val.tooltip; delete val.tooltip; }
var rng = safe_decode_range(val.ref);
for(var R=rng.s.r;R<=rng.e.r;++R) for(var C=rng.s.c;C<=rng.e.c;++C) {
var addr = encode_cell({c:C,r:R});
var addr = encode_col(C) + encode_row(R);
if(dense) {
if(!s[R]) s[R] = [];
if(!s[R][C]) s[R][C] = {t:"z",v:undefined};
s[R][C].l = val;
if(!s["!data"][R]) s["!data"][R] = [];
if(!s["!data"][R][C]) s["!data"][R][C] = {t:"z",v:undefined};
s["!data"][R][C].l = val;
} else {
if(!s[addr]) s[addr] = {t:"z",v:undefined};
s[addr].l = val;
@ -214,7 +217,7 @@ function write_ws_xml_cols(ws, cols)/*:string*/ {
}
function parse_ws_xml_autofilter(data/*:string*/) {
var o = { ref: (data.match(/ref="([^"]*)"/)||[])[1]};
var o = { ref: (data.match(/ref=["']([^"']*)["']/)||[])[1]};
return o;
}
function write_ws_xml_autofilter(data, ws, wb, idx)/*:string*/ {
@ -236,7 +239,7 @@ function write_ws_xml_autofilter(data, ws, wb, idx)/*:string*/ {
/* 18.3.1.88 sheetViews CT_SheetViews */
/* 18.3.1.87 sheetView CT_SheetView */
var sviewregex = /<(?:\w:)?sheetView(?:[^>a-z][^>]*)?\/?>/g;
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*/) {
@ -256,21 +259,27 @@ function write_ws_xml_sheetviews(ws, opts, idx, wb)/*:string*/ {
return writextag("sheetViews", writextag("sheetView", null, sview), {});
}
function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts/*::, idx, wb*/)/*:string*/ {
function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts, idx, wb, date1904)/*:string*/ {
if(cell.c) ws['!comments'].push([ref, cell.c]);
if((cell.v === undefined || cell.t === "z" && !(opts||{}).sheetStubs) && typeof cell.f !== "string" && typeof cell.z == "undefined") return "";
var vv = "";
var oldt = cell.t, oldv = cell.v;
if(cell.t !== "z") switch(cell.t) {
case 'b': vv = cell.v ? "1" : "0"; break;
case 'n': vv = ''+cell.v; break;
case 'n':
if(isNaN(cell.v)) { cell.t = "e"; vv = BErr[cell.v = 0x24]; } // #NUM!
else if(!isFinite(cell.v)) { cell.t = "e"; vv = BErr[cell.v = 0x07]; } // #DIV/0!
else vv = ''+cell.v; break;
case 'e': vv = BErr[cell.v]; break;
case 'd':
if(opts && opts.cellDates) vv = parseDate(cell.v, -1).toISOString();
else {
if(opts && opts.cellDates) {
var _vv = parseDate(cell.v, date1904);
vv = _vv.toISOString();
if(_vv.getUTCFullYear() < 1900) vv = vv.slice(vv.indexOf("T") + 1).replace("Z","");
} else {
cell = dup(cell);
cell.t = 'n';
vv = ''+(cell.v = datenum(parseDate(cell.v)));
vv = ''+(cell.v = datenum(parseDate(cell.v, date1904), date1904));
}
if(typeof cell.z === 'undefined') cell.z = table_fmt[14];
break;
@ -299,18 +308,20 @@ function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts/*::, idx, wb*/)/*:string
var ff = cell.F && cell.F.slice(0, ref.length) == ref ? {t:"array", ref:cell.F} : null;
v = writextag('f', escapexml(cell.f), ff) + (cell.v != null ? v : "");
}
if(cell.l) ws['!links'].push([ref, cell.l]);
if(cell.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 = /*#__PURE__*/(function() {
var cellregex = /<(?:\w+:)?c[ \/>]/, rowregex = /<\/(?:\w+:)?row>/;
var rregex = /r=["']([^"']*)["']/, isregex = /<(?:\w+:)?is>([\S\s]*?)<\/(?:\w+:)?is>/;
var rregex = /r=["']([^"']*)["']/;
var refregex = /ref=["']([^"']*)["']/;
var match_v = matchtag("v"), match_f = matchtag("f");
return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, themes, styles) {
return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, themes, styles, wb) {
var ri = 0, x = "", cells/*:Array<string>*/ = [], cref/*:?Array<string>*/ = [], idx=0, i=0, cc=0, d="", p/*:any*/;
var tag, tagr = 0, tagc = 0;
var sstr, ftag;
@ -318,9 +329,10 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
var do_format = Array.isArray(styles.CellXf), cf;
var arrayf/*:Array<[Range, string]>*/ = [];
var sharedf = [];
var dense = Array.isArray(s);
var dense = s["!data"] != null;
var rows/*:Array<RowInfo>*/ = [], rowobj = {}, rowrite = false;
var sheetStubs = !!opts.sheetStubs;
var date1904 = !!((wb||{}).WBProps||{}).date1904;
for(var marr = sdata.split(rowregex), mt = 0, marrlen = marr.length; mt != marrlen; ++mt) {
x = marr[mt].trim();
var xlen = x.length;
@ -349,8 +361,10 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
tag = parsexmltag(x.slice(rstarti,ri), true);
tagr = tag.r != null ? parseInt(tag.r, 10) : tagr+1; tagc = -1;
if(opts.sheetRows && opts.sheetRows < tagr) continue;
if(guess.s.r > tagr - 1) guess.s.r = tagr - 1;
if(guess.e.r < tagr - 1) guess.e.r = tagr - 1;
if(!opts.nodim) {
if(guess.s.r > tagr - 1) guess.s.r = tagr - 1;
if(guess.e.r < tagr - 1) guess.e.r = tagr - 1;
}
if(opts && opts.cellStyles) {
rowobj = {}; rowrite = false;
@ -384,23 +398,31 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
d = x.slice(i);
p = ({t:""}/*:any*/);
if((cref=d.match(match_v))!= null && /*::cref != null && */cref[1] !== '') p.v=unescapexml(cref[1]);
if((cref=str_match_xml_ns(d, "v"))!= null && /*::cref != null && */cref[1] !== '') p.v=unescapexml(cref[1]);
if(opts.cellFormula) {
if((cref=d.match(match_f))!= null && /*::cref != null && */cref[1] !== '') {
/* TODO: match against XLSXFutureFunctions */
p.f=unescapexml(utf8read(cref[1]), true);
if(!opts.xlfn) p.f = _xlfn(p.f);
if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="array"') > -1) {
p.F = (d.match(refregex)||[])[1];
if(p.F.indexOf(":") > -1) arrayf.push([safe_decode_range(p.F), p.F]);
} else if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="shared"') > -1) {
// TODO: parse formula
ftag = parsexmltag(cref[0]);
var ___f = unescapexml(utf8read(cref[1]));
if(!opts.xlfn) ___f = _xlfn(___f);
sharedf[parseInt(ftag.si, 10)] = [ftag, ___f, tag.r];
if((cref=str_match_xml_ns(d, "f"))!= null /*:: && cref != null*/) {
if(cref[1] == "") {
if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="shared"') > -1) {
// TODO: parse formula
ftag = parsexmltag(cref[0]);
if(sharedf[ftag.si]) p.f = shift_formula_xlsx(sharedf[ftag.si][1], sharedf[ftag.si][2]/*[0].ref*/, tag.r);
}
} else {
/* TODO: match against XLSXFutureFunctions */
p.f=unescapexml(utf8read(cref[1]), true);
if(!opts.xlfn) p.f = _xlfn(p.f);
if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="array"') > -1) {
p.F = (d.match(refregex)||[])[1];
if(p.F.indexOf(":") > -1) arrayf.push([safe_decode_range(p.F), p.F]);
} else if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="shared"') > -1) {
// TODO: parse formula
ftag = parsexmltag(cref[0]);
var ___f = unescapexml(utf8read(cref[1]));
if(!opts.xlfn) ___f = _xlfn(___f);
sharedf[parseInt(ftag.si, 10)] = [ftag, ___f, tag.r];
}
}
} else if((cref=d.match(/<f[^>]*\/>/))) {
} else if((cref=d.match(/<f[^<>]*\/>/))) {
ftag = parsexmltag(cref[0]);
if(sharedf[ftag.si]) p.f = shift_formula_xlsx(sharedf[ftag.si][1], sharedf[ftag.si][2]/*[0].ref*/, tag.r);
}
@ -446,7 +468,7 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
if(opts.cellHTML) p.h = escapehtml(p.v);
break;
case 'inlineStr':
cref = d.match(isregex);
cref = str_match_xml_ns(d, "is");
p.t = 's';
if(cref != null && (sstr = parse_si(cref[1]))) {
p.v = sstr.t;
@ -455,8 +477,8 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
break;
case 'b': p.v = parsexmlbool(p.v); break;
case 'd':
if(opts.cellDates) p.v = parseDate(p.v, 1);
else { p.v = datenum(parseDate(p.v, 1)); p.t = 'n'; }
if(opts.cellDates) p.v = parseDate(p.v, date1904);
else { p.v = datenum(parseDate(p.v, date1904), date1904); p.t = 'n'; }
break;
/* error string in .w, number in .v */
case 'e':
@ -475,16 +497,22 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
}
}
}
safe_format(p, fmtid, fillid, opts, themes, styles);
if(opts.cellDates && do_format && p.t == 'n' && fmt_is_date(table_fmt[fmtid])) { p.t = 'd'; p.v = numdate(p.v); }
safe_format(p, fmtid, fillid, opts, themes, styles, date1904);
if(opts.cellDates && do_format && p.t == 'n' && fmt_is_date(table_fmt[fmtid])) { p.v = numdate(p.v + (date1904 ? 1462 : 0)); p.t = typeof p.v == "number" ? 'n' : 'd'; }
if(tag.cm && opts.xlmeta) {
var cm = (opts.xlmeta.Cell||[])[+tag.cm-1];
if(cm && cm.type == 'XLDAPR') p.D = true;
}
var _r;
if(opts.nodim) {
_r = decode_cell(tag.r);
if(guess.s.r > _r.r) guess.s.r = _r.r;
if(guess.e.r < _r.r) guess.e.r = _r.r;
}
if(dense) {
var _r = decode_cell(tag.r);
if(!s[_r.r]) s[_r.r] = [];
s[_r.r][_r.c] = p;
_r = decode_cell(tag.r);
if(!s["!data"][_r.r]) s["!data"][_r.r] = [];
s["!data"][_r.r][_r.c] = p;
} else s[tag.r] = p;
}
}
@ -493,17 +521,19 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*//*::, rels*/)/*:string*/ {
var o/*:Array<string>*/ = [], r/*:Array<string>*/ = [], range = safe_decode_range(ws['!ref']), cell="", ref, rr = "", cols/*:Array<string>*/ = [], R=0, C=0, rows = ws['!rows'];
var dense = Array.isArray(ws);
var dense = ws["!data"] != null, data = dense ? ws["!data"] : [];
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) {
var data_R = dense ? data[R] : [];
if(data_R) for(C = range.s.c; C <= range.e.c; ++C) {
ref = cols[C] + rr;
var _cell = dense ? (ws[R]||[])[C]: ws[ref];
var _cell = dense ? data_R[C] : ws[ref];
if(_cell === undefined) continue;
if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb)) != null) r.push(cell);
if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb, date1904)) != null) r.push(cell);
}
if(r.length > 0 || (rows && rows[R])) {
params = ({r:rr}/*:any*/);
@ -604,11 +634,12 @@ function write_ws_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ {
if(!l[1].Target) return;
rel = ({"ref":l[0]}/*:any*/);
if(l[1].Target.charAt(0) != "#") {
rId = add_rels(rels, -1, escapexml(l[1].Target).replace(/#.*$/, ""), RELS.HLINK);
rId = add_rels(rels, -1, escapexml(l[1].Target).replace(/#[\s\S]*$/, ""), RELS.HLINK);
rel["r:id"] = "rId"+rId;
}
if((relc = l[1].Target.indexOf("#")) > -1) rel.location = escapexml(l[1].Target.slice(relc+1));
if(l[1].Tooltip) rel.tooltip = escapexml(l[1].Tooltip);
rel.display = l[1].display;
o[o.length] = writextag("hyperlink",null,rel);
});
o[o.length] = "</hyperlinks>";

@ -41,12 +41,13 @@ function write_BrtRowHdr(R/*:number*/, range, ws) {
o.l += 4;
var caddr = {r:R, c:0};
var dense = ws["!data"] != null;
for(var i = 0; i < 16; ++i) {
if((range.s.c > ((i+1) << 10)) || (range.e.c < (i << 10))) continue;
var first = -1, last = -1;
for(var j = (i<<10); j < ((i+1)<<10); ++j) {
caddr.c = j;
var cell = Array.isArray(ws) ? (ws[caddr.r]||[])[caddr.c] : ws[encode_cell(caddr)];
var cell = dense ? (ws["!data"][caddr.r]||[])[caddr.c] : ws[encode_cell(caddr)];
if(cell) { if(first < 0) first = j; last = j; }
}
if(first < 0) continue;
@ -258,9 +259,10 @@ function parse_BrtCellSt(data) {
return [cell, value, 'str'];
}
function write_BrtCellSt(cell, ncell, o) {
var data = cell.v == null ? "" : String(cell.v);
if(o == null) o = new_buf(12 + 4 * cell.v.length);
write_XLSBCell(ncell, o);
write_XLWideString(cell.v, o);
write_XLWideString(data, o);
return o.length > o.l ? o.slice(0, o.l) : o;
}
function parse_BrtShortSt(data) {
@ -269,9 +271,10 @@ function parse_BrtShortSt(data) {
return [cell, value, 'str'];
}
function write_BrtShortSt(cell, ncell, o) {
if(o == null) o = new_buf(8 + 4 * cell.v.length);
var data = cell.v == null ? "" : String(cell.v);
if(o == null) o = new_buf(8 + 4 * data.length);
write_XLSBShortCell(ncell, o);
write_XLWideString(cell.v, o);
write_XLWideString(data, o);
return o.length > o.l ? o.slice(0, o.l) : o;
}
@ -508,7 +511,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
var opts = _opts || {};
if(!rels) rels = {'!id':{}};
if(DENSE != null && opts.dense == null) opts.dense = DENSE;
var s/*:Worksheet*/ = (opts.dense ? [] : {});
var s/*:Worksheet*/ = ({}); if(opts.dense) s["!data"] = [];
var ref;
var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
@ -539,6 +542,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
XLSBRecordEnum[0x0010] = { n:"BrtShortReal", f:parse_BrtShortReal };
var cm, vm;
var date1904 = 1462 * +!!((wb||{}).WBProps||{}).date1904;
recordhopper(data, function ws_parse(val, RR, RT) {
if(end) return;
@ -582,9 +586,9 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
case 'str': p.t = 's'; p.v = val[1]; break;
case 'is': p.t = 's'; p.v = val[1].t; break;
}
if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.numFmtId,null,opts, themes, styles);
if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.numFmtId,null,opts, themes, styles, date1904>0);
C = val[0].c == -1 ? C + 1 : val[0].c;
if(opts.dense) { if(!s[R]) s[R] = []; s[R][C] = p; }
if(opts.dense) { if(!s["!data"][R]) s["!data"][R] = []; s["!data"][R][C] = p; }
else s[encode_col(C) + rr] = p;
if(opts.cellFormula) {
af = false;
@ -603,7 +607,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
if(refguess.e.r < row.r) refguess.e.r = row.r;
if(refguess.e.c < C) refguess.e.c = C;
if(opts.cellDates && cf && p.t == 'n' && fmt_is_date(table_fmt[cf.numFmtId])) {
var _d = SSF_parse_date_code(p.v); if(_d) { p.t = 'd'; p.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
var _d = SSF_parse_date_code(p.v + date1904); if(_d) { p.t = 'd'; p.v = new Date(Date.UTC(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u)); }
}
if(cm) {
if(cm.type == 'XLDAPR') p.D = true;
@ -617,7 +621,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
if(!opts.sheetStubs || pass) break;
p = ({t:'z',v:void 0}/*:any*/);
C = val[0].c == -1 ? C + 1 : val[0].c;
if(opts.dense) { if(!s[R]) s[R] = []; s[R][C] = p; }
if(opts.dense) { if(!s["!data"][R]) s["!data"][R] = []; s["!data"][R][C] = p; }
else s[encode_col(C) + rr] = p;
if(refguess.s.r > row.r) refguess.s.r = row.r;
if(refguess.s.c > C) refguess.s.c = C;
@ -648,11 +652,11 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
}
for(R=val.rfx.s.r;R<=val.rfx.e.r;++R) for(C=val.rfx.s.c;C<=val.rfx.e.c;++C) {
if(opts.dense) {
if(!s[R]) s[R] = [];
if(!s[R][C]) s[R][C] = {t:'z',v:undefined};
s[R][C].l = val;
if(!s["!data"][R]) s["!data"][R] = [];
if(!s["!data"][R][C]) s["!data"][R][C] = {t:'z',v:undefined};
s["!data"][R][C].l = val;
} else {
addr = encode_cell({c:C,r:R});
addr = encode_col(C) + encode_row(R);
if(!s[addr]) s[addr] = {t:'z',v:undefined};
s[addr].l = val;
}
@ -662,14 +666,14 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
case 0x01AA: /* 'BrtArrFmla' */
if(!opts.cellFormula) break;
arrayf.push(val);
cell = ((opts.dense ? s[R][C] : s[encode_col(C) + rr])/*:any*/);
cell = ((opts.dense ? s["!data"][R][C] : s[encode_col(C) + rr])/*:any*/);
cell.f = stringify_formula(val[1], refguess, {r:row.r, c:C}, supbooks, opts);
cell.F = encode_range(val[0]);
break;
case 0x01AB: /* 'BrtShrFmla' */
if(!opts.cellFormula) break;
sharedf[encode_cell(val[0].s)] = val[1];
cell = (opts.dense ? s[R][C] : s[encode_col(C) + rr]);
cell = (opts.dense ? s["!data"][R][C] : s[encode_col(C) + rr]);
cell.f = stringify_formula(val[1], refguess, {r:row.r, c:C}, supbooks, opts);
break;
@ -683,6 +687,10 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
}
break;
case 0x0227: /* 'BrtLegacyDrawing' */
if(val) s["!legrel"] = val;
break;
case 0x00A1: /* 'BrtBeginAFilter' */
s['!autofilter'] = { ref:encode_range(val) };
break;
@ -739,7 +747,6 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
case 0x0499: /* 'BrtFilter14' */
case 0x00A9: /* 'BrtIconFilter' */
case 0x049D: /* 'BrtIconFilter14' */
case 0x0227: /* 'BrtLegacyDrawing' */
case 0x0228: /* 'BrtLegacyDrawingHF' */
case 0x0295: /* 'BrtListPart' */
case 0x027F: /* 'BrtOleObject' */
@ -798,11 +805,12 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
if(merges.length > 0) s["!merges"] = merges;
if(colinfo.length > 0) s["!cols"] = colinfo;
if(rowinfo.length > 0) s["!rows"] = rowinfo;
if(rels['!id'][s['!legrel']]) s['!legdrawel'] = rels['!id'][s['!legrel']];
return s;
}
/* TODO: something useful -- this is a stub */
function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, ws/*:Worksheet*/, last_seen/*:boolean*/)/*:boolean*/ {
function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, ws/*:Worksheet*/, last_seen/*:boolean*/, date1904/*:boolean*/)/*:boolean*/ {
var o/*:any*/ = ({r:R, c:C}/*:any*/);
if(cell.c) ws['!comments'].push([encode_cell(o), cell.c]);
if(cell.v === undefined) return false;
@ -812,7 +820,7 @@ function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:num
case 'd': // no BrtCellDate :(
cell = dup(cell);
cell.z = cell.z || table_fmt[14];
cell.v = datenum(parseDate(cell.v)); cell.t = 'n';
cell.v = datenum(parseDate(cell.v, date1904), date1904); cell.t = 'n';
break;
/* falls through */
case 'n': case 'e': vv = ''+cell.v; break;
@ -824,7 +832,7 @@ function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:num
switch(cell.t) {
case 's': case 'str':
if(opts.bookSST) {
vv = get_sst_id(opts.Strings, (cell.v/*:any*/), opts.revStrings);
vv = get_sst_id(opts.Strings, (cell.v == null ? "" : String(cell.v)/*:any*/), opts.revStrings);
o.t = "s"; o.v = vv;
if(last_seen) write_record(ba, 0x0012 /* BrtShortIsst */, write_BrtShortIsst(cell, o));
else write_record(ba, 0x0007 /* BrtCellIsst */, write_BrtCellIsst(cell, o));
@ -839,6 +847,15 @@ function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:num
if(cell.v == (cell.v | 0) && cell.v > -1000 && cell.v < 1000) {
if(last_seen) write_record(ba, 0x000D /* BrtShortRk */, write_BrtShortRk(cell, o));
else write_record(ba, 0x0002 /* BrtCellRk */, write_BrtCellRk(cell, o));
} else if(!isFinite(cell.v)) {
o.t = "e";
if(isNaN(cell.v)) {
if(last_seen) write_record(ba, 0x000E /* BrtShortError */, write_BrtShortError({t:"e", v: 0x24}, o)); // #NUM!
else write_record(ba, 0x0003 /* BrtCellError */, write_BrtCellError({t:"e", v: 0x24},