forked from sheetjs/sheetjs
		
	Compare commits
	
		
			1 Commits
		
	
	
		
			master
			...
			maybeswapn
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 85dbed8b2c | 
| @ -11,7 +11,6 @@ | ||||
| 		"comma-dangle": [ 2, "never" ], | ||||
| 		"curly": 0, | ||||
| 		"no-bitwise": 0, | ||||
| 		"no-cond-assign": 1, | ||||
| 		"no-console": 0, | ||||
| 		"no-control-regex": 0, | ||||
| 		"no-unused-vars": 1, | ||||
|  | ||||
							
								
								
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -14,7 +14,6 @@ tmp | ||||
| *.[pP][mM][dD]* | ||||
| *.[pP][dD][fF] | ||||
| *.[sS][lL][kK] | ||||
| *.[sS][yY][lL][kK] | ||||
| *.socialcalc | ||||
| *.[xX][lL][sSwWcCaAtTmMrR] | ||||
| *.[xX][lL][sSaAtT][xXmMbB] | ||||
| @ -23,16 +22,14 @@ tmp | ||||
| *.[xX][mM][lL] | ||||
| *.[xX][lL][mM][lL] | ||||
| *.[uU][oO][sS] | ||||
| *.[wW][kKqQbB][sS1234567890] | ||||
| *.[wW][kKqQbB][S1234567890] | ||||
| *.[qQ][pP][wW] | ||||
| *.[fF][mM][3tT] | ||||
| *.[bB][iI][fF][fF][23458] | ||||
| *.[rR][tT][fF] | ||||
| *.[eE][tT] | ||||
| *.[eE][tT][hH] | ||||
| *.[nN][uU][mM][bB][eE][rR][sS] | ||||
| *.[mM][oO][dD] | ||||
| *.[dD][tT][aA] | ||||
| *.123 | ||||
| *.htm | ||||
| *.html | ||||
|  | ||||
							
								
								
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							| @ -0,0 +1,3 @@ | ||||
| [submodule "test_files"] | ||||
| 	path = test_files | ||||
| 	url = https://github.com/SheetJS/test_files | ||||
| @ -11,7 +11,6 @@ node_modules | ||||
| *.jsx | ||||
| _book | ||||
| book.json | ||||
| v8.log | ||||
| tmp | ||||
| *.[tT][xX][tT] | ||||
| *.[cC][sS][vV] | ||||
| @ -20,7 +19,6 @@ tmp | ||||
| *.[pP][mM][dD]* | ||||
| *.[pP][dD][fF] | ||||
| *.[sS][lL][kK] | ||||
| *.[sS][yY][lL][kK] | ||||
| *.socialcalc | ||||
| *.[xX][lL][sSwWcCaAtTmMrR] | ||||
| *.[xX][lL][sSaAtT][xXmMbB] | ||||
| @ -34,7 +32,6 @@ 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] | ||||
| @ -61,11 +58,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,7 +54,6 @@ Rollup | ||||
| SessionStorage | ||||
| SQLite | ||||
| SystemJS | ||||
| Vite | ||||
| VueJS | ||||
| WebKit | ||||
| WebSQL | ||||
|  | ||||
							
								
								
									
										74
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										74
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @ -4,78 +4,6 @@ This log is intended to keep track of backwards-incompatible changes, including | ||||
| but not limited to API changes and file location changes.  Minor behavioral | ||||
| changes may not be included if they are not expected to break existing code. | ||||
| 
 | ||||
| * Sheet Visibility for ODS / FODS (h/t @edemaine) | ||||
| * HTML DOM ingress support formulae (`data-f`) | ||||
| * Proper handling of XLSX encoded entities (h/t @inreoh) | ||||
| 
 | ||||
| ## v0.20.3 | ||||
| 
 | ||||
| * Correct parsing of NUMBERS and ODS merge cells (h/t @s-ashwin) | ||||
| * More precise treatment of infinite and NaN values | ||||
| * XLML Streaming Write | ||||
| * Parse `Int8Array` objects (for compatibility with JS engines in Java) | ||||
| * CSV Export only quote leading ID (h/t @lako12) | ||||
| 
 | ||||
| ## v0.20.2 | ||||
| 
 | ||||
| * Reworked parsing methods to avoid slow regexes (CVE-2024-22363) | ||||
| * HTML properly encode data-v attribute | ||||
| * SYLK read and write error cells | ||||
| 
 | ||||
| ## v0.20.1 | ||||
| 
 | ||||
| * `init` use packaged test files to work around GitHub breaking changes | ||||
| * SSF date code rounding to 15 decimal digits (h/t @davidtamaki) | ||||
| * `sheet_to_json` force UTC interpretation for formatted strings (h/t @Blanay) | ||||
| * QPW extract result of string formula | ||||
| * XLSX parse non-compliant merge cell expressions | ||||
| * NUMBERS correctly handle rows omitted from official exports | ||||
| * DBF parse empty logical field (h/t @Roman91) | ||||
| * `dense` option added to types | ||||
| * package.json add mini and core scripts to export map (h/t @stof) | ||||
| 
 | ||||
| ## v0.20.0 | ||||
| 
 | ||||
| * Use UTC interpretation of Date objects for date cells (potentially breaking) | ||||
| * API functions support UTC and local time value interpretations | ||||
| * Export `NaN` values to `#NUM!` and infinite values to `#DIV/0!` | ||||
| 
 | ||||
| ## v0.19.3 | ||||
| 
 | ||||
| * XLSX Ensure comment address is valid (h/t @slonser) | ||||
| * Enforce Excel worksheet name restrictions | ||||
| * Fixed "Prototype Pollution" vulnerability (CVE-2023-30533) | ||||
| 
 | ||||
| ## v0.19.2 | ||||
| 
 | ||||
| * XLSX proper decoding of hyperlinks (h/t @tw-yaxu) | ||||
| * XLSX ignore unexpected attributes in rich text (h/t @colin4) | ||||
| * `sheet_to_json` type fix (h/t @chsdwn) | ||||
| 
 | ||||
| ## v0.19.1 | ||||
| 
 | ||||
| * Fixed types issue in strict mode (h/t @younes-io) | ||||
| * Numbers 12.2 parsing skip ActivityStream.iwa | ||||
| 
 | ||||
| ## v0.19.0 | ||||
| 
 | ||||
| * XLSX export hyperlinks compatible with google sheets (h/t Evan Bovie) | ||||
| * NUMBERS export multiple sheets, full worksheet range | ||||
| * formalized `dense` mode | ||||
| 
 | ||||
| ## v0.18.12 | ||||
| 
 | ||||
| * `package.json` added types in `exports` structure | ||||
| * uncapped NUMBERS single-sheet single-table export | ||||
| * DBF export records using supported codepages | ||||
| 
 | ||||
| ## v0.18.11 | ||||
| 
 | ||||
| * Base64 input ignore data URI wrapper | ||||
| * Parse ZIP files that use ZIP64 extended information field | ||||
| * More precise handling of time-only values | ||||
| * Threaded Comment fallback text for older Excel | ||||
| 
 | ||||
| ## v0.18.10 | ||||
| 
 | ||||
| * `exports` field in package.json to satiate ViteJS and newer tooling | ||||
| @ -93,7 +21,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 | ||||
| 
 | ||||
|  | ||||
| @ -4,17 +4,17 @@ The SheetJS Libraries should be free and clear to use in your projects.  In | ||||
| order to maintain that, every contributor must be vigilant. | ||||
| 
 | ||||
| There have been many projects in the past that have been very lax regarding | ||||
| licensing. We are of the opinion that those are ticking timebombs and that no | ||||
| commercial product should depend on them. | ||||
| licensing, and we are of the opinion that those are ticking timebombs and that | ||||
| no commercial product should depend on them. | ||||
| 
 | ||||
| 
 | ||||
| # Required Reading | ||||
| 
 | ||||
| These are pretty short reads and emphasize the importance of proper licensing: | ||||
| 
 | ||||
| - https://github.com/jazzband/tablib/issues/114 (discussion of other tools) | ||||
| - https://github.com/kennethreitz/tablib/issues/114 (discussion of other tools) | ||||
| 
 | ||||
| - https://web.archive.org/web/20120615223756/http://www.codinghorror.com/blog/2007/04/pick-a-license-any-license.html | ||||
| - http://www.codinghorror.com/blog/2007/04/pick-a-license-any-license.html | ||||
| 
 | ||||
| 
 | ||||
| # Raising Issues | ||||
| @ -30,9 +30,10 @@ inbox is self-hosted. | ||||
| 
 | ||||
| # Opening Pull Requests | ||||
| 
 | ||||
| [Squash commits](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History) | ||||
| before opening a pull request, If the pull request addresses documentation or | ||||
| demos, add `[ci skip]` in the body or title of the commit message to skip tests. | ||||
| 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 | ||||
| 
 | ||||
| @ -56,8 +57,8 @@ issue.  If it is a particularly high-priority issue, please drop an email to | ||||
| Keep these in mind as you work: | ||||
| 
 | ||||
| - Your contributions are your original work.  Take note of any resources you | ||||
|   consult in the process. Be extra careful not to use unlicensed code on the | ||||
|   Internet or code generated by a large language model or other AI tool. | ||||
|   consult in the process (and be extra careful not to use unlicensed code on | ||||
|   the internet. | ||||
| 
 | ||||
| - You are working on your own time.  Unless they explicitly grant permission, | ||||
|   your employer may be the ultimate owner of your IP | ||||
|  | ||||
							
								
								
									
										32
									
								
								Makefile
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										32
									
								
								Makefile
									
									
									
									
									
								
							| @ -67,9 +67,10 @@ clean-data: | ||||
| 
 | ||||
| .PHONY: init | ||||
| init: ## Initial setup for development
 | ||||
| 	rm -rf test_files | ||||
| 	if [ ! -e test_files.zip ]; then curl -LO https://test-files.sheetjs.com/test_files.zip; fi | ||||
| 	unzip test_files.zip | ||||
| 	git submodule init | ||||
| 	git submodule update | ||||
| 	#git submodule foreach git pull origin master | ||||
| 	git submodule foreach make all | ||||
| 	mkdir -p tmp | ||||
| 
 | ||||
| DISTHDR=misc/suppress_export.js | ||||
| @ -106,13 +107,12 @@ dist-deps: ## Copy dependencies for distribution | ||||
| .PHONY: aux | ||||
| aux: $(AUXTARGETS) | ||||
| 
 | ||||
| BYTEFILEC=dist/xlsx.{full,core,mini}.min.js xlsx.mjs | ||||
| BYTEFILER=dist/xlsx.extendscript.js | ||||
| BYTEFILEC=dist/xlsx.{full,core,mini}.min.js | ||||
| BYTEFILER=dist/xlsx.extendscript.js xlsx.mjs | ||||
| .PHONY: bytes | ||||
| bytes: ## Display minified and gzipped file sizes
 | ||||
| 	@for i in $(BYTEFILEC); do 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,10 +140,6 @@ 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 $< | ||||
| @ -152,27 +148,22 @@ test.ts: test.mts | ||||
| 	node -pe 'var data = fs.readFileSync("'$<'", "utf8"); data.split("\n").map(function(l) { return l.replace(/^describe\((.*?)function\(\)/, "Deno.test($$1async function(t)").replace(/\b(?:it|describe)\((.*?)function\(\)/g, "await t.step($$1async function(t)").replace("assert.ok", "assert.assert"); }).join("\n")' > $@ | ||||
| 
 | ||||
| .PHONY: test-bun | ||||
| test-bun: test.test.mjs ## Run Bun test suite
 | ||||
| 	bun test $< | ||||
| test-bun: hotcross.mjs ## Run Bun test suite
 | ||||
| 	bun $< | ||||
| 
 | ||||
| .PHONY: test-deno | ||||
| test-deno: test.ts ## Run Deno test suite
 | ||||
| 	deno test --check --allow-env --allow-read --allow-write --config misc/test.deno.jsonc $< | ||||
| 	deno test --allow-env --allow-read --allow-write --config misc/test.deno.jsonc $< | ||||
| 
 | ||||
| .PHONY: test-denocp | ||||
| test-denocp: testnocp.ts ## Run Deno test suite (without codepage)
 | ||||
| 	deno test --check --allow-env --allow-read --allow-write --config misc/test.deno.jsonc $< | ||||
| 	deno test --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_%: | ||||
| @ -254,7 +245,8 @@ misc/coverage.html: $(TARGET) test.js | ||||
| coveralls: ## Coverage Test + Send to coveralls.io
 | ||||
| 	mocha --require blanket --reporter mocha-lcov-reporter -t 30000 | node ./node_modules/coveralls/bin/coveralls.js | ||||
| 
 | ||||
| MDLINT=README.md | ||||
| DEMOMDS=$(sort $(wildcard demos/*/README.md)) | ||||
| MDLINT=$(DEMOMDS) README.md demos/README.md | ||||
| .PHONY: mdlint | ||||
| mdlint: $(MDLINT) ## Check markdown documents
 | ||||
| 	./node_modules/.bin/alex $^ | ||||
|  | ||||
							
								
								
									
										22
									
								
								README.md
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										22
									
								
								README.md
									
									
									
									
									
								
							| @ -9,27 +9,35 @@ 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! | ||||
| 
 | ||||
| [](https://github.com/SheetJS/sheetjs/blob/master/LICENSE) | ||||
| [](https://github.com/SheetJS/sheetjs/actions) | ||||
| [](https://snyk.io/test/github/SheetJS/sheetjs) | ||||
| [](https://cdn.sheetjs.com/) | ||||
| [](https://github.com/SheetJS/sheetjs) | ||||
| 
 | ||||
| [](https://github.com/SheetJS/sheetjs) | ||||
| 
 | ||||
| [](https://saucelabs.com/u/sheetjs) | ||||
| 
 | ||||
| ## Documentation | ||||
| 
 | ||||
| - [API and Usage Documentation](https://docs.sheetjs.com) | ||||
| 
 | ||||
| - [Downloadable Scripts and Modules](https://cdn.sheetjs.com) | ||||
| 
 | ||||
| ## Constellation | ||||
| ## Related Projects | ||||
| 
 | ||||
| - <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 | ||||
| 
 | ||||
| - [`cfb`](https://git.sheetjs.com/SheetJS/js-cfb): Container (OLE/ZIP) file | ||||
| processing library | ||||
| - [`test_files`](https://github.com/SheetJS/test_files): Sample spreadsheets | ||||
| 
 | ||||
| - [`codepage`](https://git.sheetjs.com/SheetJS/js-codepage): Legacy text | ||||
| encodings for XLS and other legacy spreadsheet formats | ||||
| - [`cfb`](https://github.com/SheetJS/js-cfb): Container (OLE/ZIP) format library | ||||
| 
 | ||||
| - [`dta`](packages/dta): Stata DTA file processor | ||||
| - [`codepage`](https://github.com/SheetJS/js-codepage): Legacy text encodings | ||||
| 
 | ||||
| ## License | ||||
| 
 | ||||
|  | ||||
| @ -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, Set:false, Float32Array:false */ | ||||
| /*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false */ | ||||
| var XLSX = {}; | ||||
| function make_xlsx_lib(XLSX){ | ||||
|  | ||||
| @ -1 +1 @@ | ||||
| XLSX.version = '0.20.3'; | ||||
| XLSX.version = '0.18.10'; | ||||
|  | ||||
| @ -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,11 +41,6 @@ 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,34 +45,9 @@ 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; | ||||
|   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++)); | ||||
|  | ||||
| @ -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") o.set(new Uint8Array(s2a(bufs[i])), maxlen); | ||||
| 			else if(typeof bufs[i] == "string") { throw "wtf"; } | ||||
| 			else o.set(new Uint8Array(bufs[i]), maxlen); | ||||
| 		} | ||||
| 		return o; | ||||
|  | ||||
| @ -173,20 +173,8 @@ 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}; | ||||
| @ -215,6 +203,15 @@ 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 */ | ||||
| @ -243,7 +240,6 @@ 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); | ||||
| @ -273,7 +269,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(v, opts && opts.date1904), opts); | ||||
| 			if(v instanceof Date) return SSF_format(14, datenum_local(v, opts && opts.date1904), opts); | ||||
| 	} | ||||
| 	throw new Error("unsupported value in General format: " + v); | ||||
| } | ||||
| @ -341,7 +337,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+(ss0 == 0 ? Math.round(val.S+val.u) : val.S); break; | ||||
| 			case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+Math.round(val.S+val.u); break; | ||||
| 			default: throw 'bad abstime format: ' + fmt; | ||||
| 		} outl = fmt.length === 3 ? 1 : 2; break; | ||||
| 		case 101: /* 'e' era */ | ||||
| @ -409,7 +405,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; | ||||
| @ -789,11 +785,10 @@ 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); bt = 4;} | ||||
| 				if((ssm=out[i].v.match(/\.0+$/))) ss0=Math.max(ss0,ssm[0].length-1); | ||||
| 				if(bt < 3) bt = 3; | ||||
| 			/* falls through */ | ||||
| 			case 'd': case 'y': case 'e': lst=out[i].t; break; | ||||
| 			case 'M': lst=out[i].t; if(bt < 2) bt = 2; break; | ||||
| 			case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break; | ||||
| 			case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break; | ||||
| 			case 'X': /*if(out[i].v === "B2");*/ | ||||
| 				break; | ||||
| @ -803,29 +798,19 @@ 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: | ||||
| 		case 2: | ||||
| 		case 3: | ||||
| 			/*::if(!dt) break;*/ | ||||
| 			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 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; } | ||||
| 		case 2: | ||||
| 			/*::if(!dt) break;*/ | ||||
| 			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; | ||||
| 	} | ||||
| 
 | ||||
| @ -941,8 +926,6 @@ 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; | ||||
| @ -974,13 +957,11 @@ 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(v, o.date1904); | ||||
| 	if(v instanceof Date) v = datenum_local(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,7 +43,6 @@ 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*/ { | ||||
| @ -56,7 +55,6 @@ 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,9 +42,7 @@ type CFBFiles = {[n:string]:CFBEntry}; | ||||
| var CRC32 = /*#__PURE__*/(function() { | ||||
| var CRC32 = {}; | ||||
| CRC32.version = '1.2.0'; | ||||
| /*:: | ||||
| type CRC32TableType = Array<number> | Int32Array; | ||||
| */ | ||||
| /* see perf/crc32table.js */ | ||||
| /*global Int32Array */ | ||||
| function signed_crc_table()/*:any*/ { | ||||
| 	var c = 0, table/*:Array<number>*/ = new Array(256); | ||||
| @ -75,14 +73,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' && typeof table.subarray == "function" ? 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' ? 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; | ||||
| @ -213,15 +211,8 @@ function parse_extra_field(blob/*:CFBlob*/)/*:any*/ { | ||||
| 					if(flags & 4) p.ctime = blob.read_shift(4); | ||||
| 				} | ||||
| 				if(p.mtime) p.mt = new Date(p.mtime*1000); | ||||
| 			} break; | ||||
| 			/* ZIP64 Extended Information Field */ | ||||
| 			case 0x0001: { | ||||
| 				var sz1 = blob.read_shift(4), sz2 = blob.read_shift(4); | ||||
| 				p.usz = (sz2 * Math.pow(2,32) + sz1); | ||||
| 				sz1 = blob.read_shift(4); sz2 = blob.read_shift(4); | ||||
| 				p.csz = (sz2 * Math.pow(2,32) + sz1); | ||||
| 				// NOTE: volume fields are skipped
 | ||||
| 			} break; | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 		blob.l = tgt; | ||||
| 		o[type] = p; | ||||
| @ -308,7 +299,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); | ||||
| 
 | ||||
| if(dir_start < sector_list.length) sector_list[dir_start].name = "!Directory"; | ||||
| 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; | ||||
| @ -771,9 +762,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 > 31) { | ||||
| 			console.error("Name " + _nm + " will be truncated to " + _nm.slice(0,31)); | ||||
| 			_nm = _nm.slice(0, 31); | ||||
| 		if(_nm.length > 32) { | ||||
| 			console.error("Name " + _nm + " will be truncated to " + _nm.slice(0,32)); | ||||
| 			_nm = _nm.slice(0, 32); | ||||
| 		} | ||||
| 		flen = 2*(_nm.length+1); | ||||
| 		o.write_shift(64, _nm, "utf16le"); | ||||
| @ -1410,11 +1401,6 @@ function parse_zip(file/*:RawBytes*/, options/*:CFBReadOpts*/)/*:CFBContainer*/ | ||||
| 
 | ||||
| 		var L = blob.l; | ||||
| 		blob.l = offset + 4; | ||||
| 		/* ZIP64 lengths */ | ||||
| 		if(EF && EF[0x0001]) { | ||||
| 			if((EF[0x0001]||{}).usz) usz = EF[0x0001].usz; | ||||
| 			if((EF[0x0001]||{}).csz) csz = EF[0x0001].csz; | ||||
| 		} | ||||
| 		parse_local_file(blob, csz, usz, o, EF); | ||||
| 		blob.l = L; | ||||
| 	} | ||||
| @ -1444,13 +1430,7 @@ function parse_local_file(blob/*:CFBlob*/, csz/*:number*/, usz/*:number*/, o/*:C | ||||
| 	if(efsz) { | ||||
| 		var ef = parse_extra_field(/*::(*/blob.slice(blob.l, blob.l + efsz)/*:: :any)*/); | ||||
| 		if((ef[0x5455]||{}).mt) date = ef[0x5455].mt; | ||||
| 		if((ef[0x0001]||{}).usz) _usz = ef[0x0001].usz; | ||||
| 		if((ef[0x0001]||{}).csz) _csz = ef[0x0001].csz; | ||||
| 		if(EF) { | ||||
| 			if((EF[0x5455]||{}).mt) date = EF[0x5455].mt; | ||||
| 			if((EF[0x0001]||{}).usz) _usz = EF[0x0001].usz; | ||||
| 			if((EF[0x0001]||{}).csz) _csz = EF[0x0001].csz; | ||||
| 		} | ||||
| 		if(((EF||{})[0x5455]||{}).mt) date = EF[0x5455].mt; | ||||
| 	} | ||||
| 	blob.l += efsz; | ||||
| 
 | ||||
| @ -1460,7 +1440,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: blob.l += _csz; break; // TODO: scan for magic number
 | ||||
| 		case 0: break; // TODO: scan for magic number
 | ||||
| 		default: throw new Error("Unsupported ZIP Compression method " + meth); | ||||
| 	} | ||||
| 
 | ||||
| @ -1495,17 +1475,16 @@ 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 || (Array.isArray(fi.content) && fi.content.length == 0) || fp == "\u0001Sh33tJ5") continue; | ||||
| 		if(!fi.size || !fi.content || 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] = typeof fi.content == "string" ? CRC32.bstr(fi.content, 0) : CRC32.buf(/*::((*/fi.content/*::||[]):any)*/, 0); | ||||
| 		crcs[fcnt] = CRC32.buf(/*::((*/fi.content/*::||[]):any)*/, 0); | ||||
| 
 | ||||
| 		var outbuf = typeof fi.content == "string" ? s2a(fi.content) : fi.content/*::||[]*/; | ||||
| 		var outbuf = fi.content/*::||[]*/; | ||||
| 		if(method == 8) outbuf = _deflateRawSync(outbuf); | ||||
| 
 | ||||
| 		/* local file header */ | ||||
| @ -1686,7 +1665,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,10 +45,6 @@ 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
 | ||||
| @ -57,7 +53,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.indexOf("onstruct") == -1) throw e; } | ||||
| 	} catch(e) { if(!e.message || !e.message.match(/onstruct/)) throw e; } | ||||
| 	throw new Error("cannot save file " + fname); | ||||
| } | ||||
| 
 | ||||
| @ -71,6 +67,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.indexOf("onstruct") == -1) throw e; } | ||||
| 	} catch(e) { if(!e.message || !e.message.match(/onstruct/)) throw e; } | ||||
| 	throw new Error("Cannot access file " + path); | ||||
| } | ||||
|  | ||||
| @ -31,19 +31,22 @@ function evert_arr(obj/*:any*/)/*:EvertArrType*/ { | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| var dnthresh  = /*#__PURE__*/Date.UTC(1899, 11, 30, 0, 0, 0); // -2209161600000
 | ||||
| var dnthresh1 = /*#__PURE__*/Date.UTC(1899, 11, 31, 0, 0, 0); // -2209075200000
 | ||||
| var dnthresh2 = /*#__PURE__*/Date.UTC(1904, 0, 1, 0, 0, 0); // -2209075200000
 | ||||
| var basedate = /*#__PURE__*/new Date(1899, 11, 30, 0, 0, 0); // 2209161600000
 | ||||
| function datenum(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ { | ||||
| 	var epoch = /*#__PURE__*/v.getTime(); | ||||
| 	var res = (epoch - dnthresh) / (24 * 60 * 60 * 1000); | ||||
| 	if(date1904) { res -= 1462; return res < -1402 ? res - 1 : res; } | ||||
| 	return res < 60 ? res - 1 : res; | ||||
| 	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); | ||||
| } | ||||
| function numdate(v/*:number*/)/*:Date|number*/ { | ||||
| 	if(v >= 60 && v < 61) return v; | ||||
| var refdate = /*#__PURE__*/new Date(); | ||||
| var dnthresh = /*#__PURE__*/basedate.getTime() + (/*#__PURE__*/refdate.getTimezoneOffset() - /*#__PURE__*/basedate.getTimezoneOffset()) * 60000; | ||||
| var refoffset = /*#__PURE__*/refdate.getTimezoneOffset(); | ||||
| function numdate(v/*:number*/)/*:Date*/ { | ||||
| 	var out = new Date(); | ||||
| 	out.setTime((v>60 ? v : (v+1)) * 24 * 60 * 60 * 1000 + dnthresh); | ||||
| 	out.setTime(v * 24 * 60 * 60 * 1000 + dnthresh); | ||||
| 	if (out.getTimezoneOffset() !== refoffset) { | ||||
| 		out.setTime(out.getTime() + (out.getTimezoneOffset() - refoffset) * 60000); | ||||
| 	} | ||||
| 	return out; | ||||
| } | ||||
| 
 | ||||
| @ -74,22 +77,28 @@ function parse_isodur(s) { | ||||
| 	return sec; | ||||
| } | ||||
| 
 | ||||
| /* Blame https://bugs.chromium.org/p/v8/issues/detail?id=7863 for the regexide */ | ||||
| var pdre1 = /^(\d+):(\d+)(:\d+)?(\.\d+)?$/; // HH:MM[:SS[.UUU]]
 | ||||
| var pdre2 = /^(\d+)-(\d+)-(\d+)$/; // YYYY-mm-dd
 | ||||
| var pdre3 = /^(\d+)-(\d+)-(\d+)[T ](\d+):(\d+)(:\d+)?(\.\d+)?$/; // YYYY-mm-dd(T or space)HH:MM[:SS[.UUU]], sans "Z"
 | ||||
| /* parses a date string as a UTC date */ | ||||
| function parseDate(str/*:string*/, date1904/*:boolean*/)/*:Date*/ { | ||||
| 	if(str instanceof Date) return str; | ||||
| 	var m = str.match(pdre1); | ||||
| 	if(m) return new Date((date1904 ? dnthresh2 : dnthresh1) + ((parseInt(m[1], 10)*60 + parseInt(m[2], 10))*60 + (m[3] ? parseInt(m[3].slice(1), 10) : 0))*1000 + (m[4] ? parseInt((m[4]+"000").slice(1,4), 10) : 0)); | ||||
| 	m = str.match(pdre2); | ||||
| 	if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], 0, 0, 0, 0)); | ||||
| 	/* TODO: 1900-02-29T00:00:00.000 should return a flag to treat as a date code (affects xlml) */ | ||||
| 	m = str.match(pdre3); | ||||
| 	if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], +m[4], +m[5], ((m[6] && parseInt(m[6].slice(1), 10))|| 0), ((m[7] && parseInt((m[7] + "0000").slice(1,4), 10))||0))); | ||||
| var 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); | ||||
| 	return d; | ||||
| 	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; | ||||
| 	} | ||||
| 	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; | ||||
| } | ||||
| 
 | ||||
| function cc2str(arr/*:Array<number>*/, debomit)/*:string*/ { | ||||
| @ -120,18 +129,8 @@ 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 = [], 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])); | ||||
| 		} | ||||
| 	} | ||||
| 	var o = []; | ||||
| 	for(var i = 0; i != arr.length; ++i) o.push(String.fromCharCode(arr[i])); | ||||
| 	return o.join(""); | ||||
| } | ||||
| 
 | ||||
| @ -154,56 +153,39 @@ 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*/ { | ||||
| 	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)); | ||||
|     /* TODO: 1904 adjustment, keep in sync with base date */ | ||||
|     if(!M[2]) return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), 0, 0, 0); | ||||
|     if(M[3]) { | ||||
|         if(M[4]) return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[4], parseFloat(M[3])*1000); | ||||
|         else return new Date(1899,11,30,(M[7] == "p" ? 12 : 0), +M[1], +M[2], parseFloat(M[3])*1000); | ||||
|     } | ||||
|     else if(M[5]) return new Date(1899,11,30, (+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[5], M[6] ? parseFloat(M[6]) * 1000 : 0); | ||||
|     else return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], 0, 0); | ||||
| } | ||||
| var lower_months = ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december']; | ||||
| function fuzzydate(s/*:string*/)/*:Date*/ { | ||||
| 	// See issue 2863 -- this is technically not supported in Excel but is otherwise useful
 | ||||
| 	if(FDISO.test(s)) return s.indexOf("Z") == -1 ? local_to_utc(new Date(s)) : new Date(s); | ||||
| 	var lower = s.toLowerCase(); | ||||
| 	var lnos = lower.replace(/\s+/g, " ").trim(); | ||||
| 	var M = lnos.match(FDRE1); | ||||
| 	if(M) return fuzzytime1(M); | ||||
| 	M = lnos.match(FDRE2); | ||||
| 	if(M) return fuzzytime2(M); | ||||
| 	M = lnos.match(pdre3); | ||||
| 	if(M) return new Date(Date.UTC(+M[1], +M[2]-1, +M[3], +M[4], +M[5], ((M[6] && parseInt(M[6].slice(1), 10))|| 0), ((M[7] && parseInt((M[7] + "0000").slice(1,4), 10))||0))); | ||||
| 	var o = new Date(utc_append_works && s.indexOf("UTC") == -1 ? s + " UTC": s), n = new Date(NaN); | ||||
| 
 | ||||
| 	var o = new Date(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; | ||||
| } | ||||
| 
 | ||||
| @ -216,165 +198,3 @@ 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,9 +67,6 @@ 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*((?:")([^"]*)(?:")|(?:')([^']*)(?:')|([^'">\s]+))/g; | ||||
| var tagregex1=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?<>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'"<>\s=]+))*\s*[\/\?]?>/mg, tagregex2 = /<[^<>]*>/g; | ||||
| var attregexg=/([^"\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].slice(1); | ||||
| 		cc = m[i]; | ||||
| 		for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break; | ||||
| 		q = cc.slice(0,c).trim(); | ||||
| 		while(cc.charCodeAt(c+1) == 32) ++c; | ||||
| @ -32,26 +32,6 @@ 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 = { | ||||
| @ -67,7 +47,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})_/g; | ||||
| 	var encregex = /&(?:quot|apos|gt|lt|amp|#x?([\da-fA-F]+));/ig, coderegex = /_x([\da-fA-F]{4})_/ig; | ||||
| 	function raw_unescapexml(text/*:string*/)/*:string*/ { | ||||
| 		var s = text + '', i = s.indexOf("<![CDATA["); | ||||
| 		if(i == -1) return s.replace(encregex, function($$, $1) { return encodings[$$]||String.fromCharCode(parseInt($1,$$.indexOf("x")>-1?16:10))||$$; }).replace(coderegex,function(m,c) {return String.fromCharCode(parseInt(c,16));}); | ||||
| @ -181,6 +161,16 @@ 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', '·'], | ||||
| @ -191,25 +181,30 @@ 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 ])[\t\n\r ]+$/,"$1") | ||||
| 				.replace(/[\t\n\r ]+$/,"") | ||||
| 				// Added line which removes any white space characters after and before html tags
 | ||||
| 				.replace(/>\s+/g,">").replace(/\b\s+</g,"<") | ||||
| 				.replace(/>\s+/g,">").replace(/\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 vtvregex = /<\/?(?:vt:)?variant>/g, vtmregex = /<(?:vt:)([^<"'>]*)>([\s\S]*)</; | ||||
| 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]*)</; | ||||
| function parseVector(data/*:string*/, opts)/*:Array<{v:string,t:string}>*/ { | ||||
| 	var h = parsexmltag(data); | ||||
| 
 | ||||
| 	var matches/*:Array<string>*/ = str_match_xml_ns_g(data, h.baseType)||[]; | ||||
| 	var matches/*:Array<string>*/ = data.match(vtregex(h.baseType))||[]; | ||||
| 	var res/*:Array<any>*/ = []; | ||||
| 	if(matches.length != h.size) { | ||||
| 		if(opts.WTF) throw new Error("unexpected vector length " + matches.length + " != " + h.size); | ||||
| @ -250,8 +245,9 @@ 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, ODS uses invalid XML */ | ||||
| var xlmlregex = /<([\/]?)([^\s?><!\/:"]*:|)([^\s?<>:\/"]+)(?:\s+[^<>=?"'\s]+="[^"]*?")*\s*[\/]?>/mg; | ||||
| /* UOS uses CJK in tags */ | ||||
| var xlmlregex = /<(\/?)([^\s?><!\/:]*:|)([^\s?<>:\/]+)(?:[\s?:\/](?:[^>=]|="[^"]*?")*)?>/mg; | ||||
| //var xlmlregex = /<(\/?)([a-z0-9]*:|)(\w+)[^>]*>/mg;
 | ||||
| 
 | ||||
| var XMLNS = ({ | ||||
| 	CORE_PROPS: 'http://schemas.openxmlformats.org/package/2006/metadata/core-properties', | ||||
|  | ||||
| @ -181,29 +181,21 @@ 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' || f == 'cpstr') { | ||||
| 	} else if(f === 'sbcs') { | ||||
| 		if(typeof $cptable !== 'undefined' && current_ansi == 874) { | ||||
| 			/* TODO: use tables directly, don't encode */ | ||||
| 			/*:: if(typeof val !== "string") throw new Error("unreachable"); */ | ||||
| 			for(i = 0; i != val.length; ++i) { | ||||
| 				var cpp = $cptable.utils.encode(current_ansi, val.charAt(i)); | ||||
| 				this[this.l + i] = cpp[0]; | ||||
| 				var cppayload = $cptable.utils.encode(current_ansi, val.charAt(i)); | ||||
| 				this[this.l + i] = cppayload[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,8 +20,7 @@ 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 ? 16384 : 2048; | ||||
| 	var has_buf_copy = has_buf && (typeof new_buf(blksz).copy == "function"); | ||||
| 	var bufs/*:Array<Block>*/ = [], blksz = has_buf ? 256 : 2048; | ||||
| 	var newblk = function ba_newblk(sz/*:number*/)/*:Block*/ { | ||||
| 		var o/*:Block*/ = (new_buf(sz)/*:any*/); | ||||
| 		prep_blob(o, 0); | ||||
| @ -50,15 +49,10 @@ 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) { endbuf(); curbuf = buf; if(curbuf.l == null) curbuf.l = curbuf.length; next(blksz); }; | ||||
| 
 | ||||
| 	return ({ next:next, push:push, end:end, _bufs:bufs, end2:end2 }/*:any*/); | ||||
| 	return ({ next:next, push:push, end:end, _bufs:bufs }/*:any*/); | ||||
| } | ||||
| 
 | ||||
| function write_record(ba/*:BufArray*/, type/*:number*/, payload, length/*:?number*/) { | ||||
|  | ||||
| @ -9,6 +9,7 @@ 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) { | ||||
| @ -18,6 +19,7 @@ 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=""; | ||||
| @ -108,19 +110,11 @@ 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 ? (_ws["!data"] != null) : o.dense; | ||||
| 	var dense = _ws ? Array.isArray(_ws) : o.dense; | ||||
| 	if(DENSE != null && dense == null) dense = DENSE; | ||||
| 	var ws/*:Worksheet*/ = _ws || (dense ? ({"!data": []}) : ({}/*:any*/)); | ||||
| 	if(dense && !ws["!data"]) ws["!data"] = []; | ||||
| 	var ws/*:Worksheet*/ = _ws || (dense ? ([]/*:any*/) : ({}/*:any*/)); | ||||
| 	var _R = 0, _C = 0; | ||||
| 	if(ws && o.origin != null) { | ||||
| 		if(typeof o.origin == 'number') _R = o.origin; | ||||
| @ -128,71 +122,63 @@ 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 = (ws["!ref"] ? _range.e.r + 1 : 0); | ||||
| 	} else { | ||||
| 		range.s.c = range.e.c = range.s.r = range.e.r = 0; | ||||
| 		if(_R == -1) range.e.r = _R = _range.e.r + 1; | ||||
| 	} | ||||
| 	var row = [], seen = false; | ||||
| 	for(var R = 0; R != data.length; ++R) { | ||||
| 		if(!data[R]) continue; | ||||
| 		if(!Array.isArray(data[R])) throw new Error("aoa_to_sheet expects an array of arrays"); | ||||
| 		var __R = _R + R; | ||||
| 		if(dense) { | ||||
| 			if(!ws["!data"][__R]) ws["!data"][__R] = []; | ||||
| 			row = ws["!data"][__R]; | ||||
| 		} | ||||
| 		var data_R = data[R]; | ||||
| 		for(var C = 0; C != data_R.length; ++C) { | ||||
| 			if(typeof data_R[C] === 'undefined') continue; | ||||
| 			var cell/*:Cell*/ = ({v: data_R[C], t:"" }/*:any*/); | ||||
| 			var __C = _C + C; | ||||
| 		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; | ||||
| 			if(range.s.r > __R) range.s.r = __R; | ||||
| 			if(range.s.c > __C) range.s.c = __C; | ||||
| 			if(range.e.r < __R) range.e.r = __R; | ||||
| 			if(range.e.c < __C) range.e.c = __C; | ||||
| 			seen = true; | ||||
| 			if(data_R[C] && typeof data_R[C] === 'object' && !Array.isArray(data_R[C]) && !(data_R[C] instanceof Date)) cell = data_R[C]; | ||||
| 			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') { | ||||
| 					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 === 'number') cell.t = 'n'; | ||||
| 				else if(typeof cell.v === 'boolean') cell.t = 'b'; | ||||
| 				else if(cell.v instanceof Date) { | ||||
| 					cell.z = o.dateNF || table_fmt[14]; | ||||
| 					if(!o.UTC) cell.v = local_to_utc(cell.v); | ||||
| 					if(o.cellDates) { cell.t = 'd'; cell.w = SSF_format(cell.z, datenum(cell.v, o.date1904)); } | ||||
| 					else { cell.t = 'n'; cell.v = datenum(cell.v, o.date1904); cell.w = SSF_format(cell.z, cell.v); } | ||||
| 				} | ||||
| 				else cell.t = 's'; | ||||
| 			} | ||||
| 			if(dense) { | ||||
| 				if(row[__C] && row[__C].z) cell.z = row[__C].z; | ||||
| 				row[__C] = cell; | ||||
| 				if(!ws[__R]) ws[__R] = []; | ||||
| 				if(ws[__R][__C] && ws[__R][__C].z) cell.z = ws[__R][__C].z; | ||||
| 				ws[__R][__C] = cell; | ||||
| 			} else { | ||||
| 				var cell_ref = encode_col(__C) + (__R + 1)/*:any*/; | ||||
| 				var cell_ref = encode_cell(({c:__C,r:__R}/*:any*/)); | ||||
| 				if(ws[cell_ref] && ws[cell_ref].z) cell.z = ws[cell_ref].z; | ||||
| 				ws[cell_ref] = cell; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	if(seen && range.s.c < 10400000) ws['!ref'] = encode_range(range); | ||||
| 	if(range.s.c < 10000000) { | ||||
| 		if(range.s.c > _C) range.s.c = _C; | ||||
| 		if(range.s.r > _R) range.s.r = _R; | ||||
| 		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 = unescapexml(y.Target); rel.Id = y.Id; if(y.TargetMode) rel.TargetMode = y.TargetMode; | ||||
| 			var rel = {}; rel.Type = y.Type; rel.Target = 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,61 +1,62 @@ | ||||
| /* 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; | ||||
|       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; | ||||
|     } | ||||
| 	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; | ||||
| 	} | ||||
| } | ||||
| function write_manifest(manifest) { | ||||
|   var o = [XML_HEADER]; | ||||
|   o.push('<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2">\n'); | ||||
|   o.push('  <manifest:file-entry manifest:full-path="/" manifest:version="1.2" manifest:media-type="application/vnd.oasis.opendocument.spreadsheet"/>\n'); | ||||
|   for (var i = 0; i < manifest.length; ++i) | ||||
|     o.push('  <manifest:file-entry manifest:full-path="' + manifest[i][0] + '" manifest:media-type="' + manifest[i][1] + '"/>\n'); | ||||
|   o.push("</manifest:manifest>"); | ||||
|   return o.join(""); | ||||
| 
 | ||||
| function write_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_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(""); | ||||
| 
 | ||||
| /* 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_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_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(rdf) { | ||||
|   var o = [XML_HEADER]; | ||||
|   o.push('<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">\n'); | ||||
|   for (var i = 0; i != rdf.length; ++i) { | ||||
|     o.push(write_rdf_type(rdf[i][0], rdf[i][1])); | ||||
|     o.push(write_rdf_has("", rdf[i][0])); | ||||
|   } | ||||
|   o.push(write_rdf_type("", "Document", "pkg")); | ||||
|   o.push("</rdf:RDF>"); | ||||
|   return o.join(""); | ||||
| 	var o = [XML_HEADER]; | ||||
| 	o.push('<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">\n'); | ||||
| 	for(var i = 0; i != rdf.length; ++i) { | ||||
| 		o.push(write_rdf_type(rdf[i][0], rdf[i][1])); | ||||
| 		o.push(write_rdf_has("",rdf[i][0])); | ||||
| 	} | ||||
| 	o.push(write_rdf_type("","Document", "pkg")); | ||||
| 	o.push('</rdf:RDF>'); | ||||
| 	return o.join(""); | ||||
| } | ||||
| function write_meta_ods(wb, opts) { | ||||
|   return '<office:document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xlink="http://www.w3.org/1999/xlink" office:version="1.2"><office:meta><meta:generator>SheetJS ' + XLSX.version + "</meta:generator></office:meta></office:document-meta>"; | ||||
| /* TODO: pull properties */ | ||||
| function write_meta_ods(/*:: wb: Workbook, opts: any*/)/*:string*/ { | ||||
| 	return '<office:document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xlink="http://www.w3.org/1999/xlink" office:version="1.2"><office:meta><meta:generator>Sheet' + 'JS ' + XLSX.version + '</meta:generator></office:meta></office:document-meta>'; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -18,12 +18,22 @@ 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 = str_match_xml(data, f[0]); | ||||
| 		var f = CORE_PROPS[i], cur = data.match(CORE_PROPS_REGEX[i]); | ||||
| 		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 = (str_match_xml_ns(data, f[0])||[])[1]; | ||||
| 		var xml = (data.match(matchtag(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 = str_match_xml(data, f[0]); | ||||
| 				var cur = data.match(new RegExp("<" + f[0] + "[^>]*>([\\s\\S]*?)<\/" + f[0] + ">")); | ||||
| 				if(cur && cur.length > 0) q[f[1]] = cur[1]; | ||||
| 				break; | ||||
| 		} | ||||
|  | ||||
| @ -1,11 +1,11 @@ | ||||
| /* 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); | ||||
| 	if(m) for(var i = 0; i != m.length; ++i) { | ||||
| 		var x = m[i], y = parsexmltag(x); | ||||
| 		switch(strip_ns(y[0])) { | ||||
| 		switch(y[0]) { | ||||
| 			case '<?xml': break; | ||||
| 			case '<Properties': break; | ||||
| 			case '<property': name = unescapexml(y.name); break; | ||||
|  | ||||
| @ -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*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/(^|[^\u0000])\u0000+$/,"$1"); break; | ||||
| 		case 0x1F /*VT_LPWSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/(^|[^\u0000])\u0000+$/,"$1"); break; | ||||
| 		case 0x1E /*VT_LPSTR*/: return parse_lpstr(blob, t, 4).replace(chr0,''); | ||||
| 		case 0x1F /*VT_LPWSTR*/: return parse_lpwstr(blob); | ||||
| 		case 0x40 /*VT_FILETIME*/: return parse_FILETIME(blob); | ||||
| 		case 0x41 /*VT_BLOB*/: return parse_BLOB(blob); | ||||
| 		case 0x47 /*VT_CF*/: return parse_ClipboardData(blob); | ||||
| @ -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])\u0000+$/,"$1"); break; | ||||
| 					case 0x1F /*VT_LPWSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/(^|[^\u0000])\u0000+$/,"$1"); break; | ||||
| 					case 0x1E /*VT_LPSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/\u0000+$/,""); break; | ||||
| 					case 0x1F /*VT_LPWSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/\u0000+$/,""); 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,20 +1,9 @@ | ||||
| /* [MS-XLS] 2.5.19 */ | ||||
| function parse_XLSCell(blob, length, opts)/*:Cell*/ { | ||||
| function parse_XLSCell(blob/*::, length*/)/*:Cell*/ { | ||||
| 	var rw = blob.read_shift(2); // 0-indexed
 | ||||
| 	var col = blob.read_shift(2); | ||||
| 	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; | ||||
| 	var ixfe = blob.read_shift(2); | ||||
| 	return ({r:rw, c:col, ixfe:ixfe}/*:any*/); | ||||
| } | ||||
| function write_XLSCell(R/*:number*/, C/*:number*/, ixfe/*:?number*/, o) { | ||||
| 	if(!o) o = new_buf(6); | ||||
| @ -122,25 +111,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; | ||||
| @ -149,7 +138,7 @@ function parse_FtArray(blob, length/*::, ot*/) { | ||||
| 		var ft = blob.read_shift(2); | ||||
| 		blob.l-=2; | ||||
| 		try { | ||||
| 			fts[ft] = FtTab[ft](blob, tgt - blob.l); | ||||
| 			fts.push(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");
 | ||||
| @ -239,12 +228,6 @@ 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); | ||||
| @ -254,7 +237,7 @@ function parse_BoundSheet8(blob, length, opts) { | ||||
| 		case 2: dt = 'Chartsheet'; break; | ||||
| 		case 6: dt = 'VBAModule'; break; | ||||
| 	} | ||||
| 	name = parse_ShortXLUnicodeString(blob, 0, opts); | ||||
| 	var name = parse_ShortXLUnicodeString(blob, 0, opts); | ||||
| 	if(name.length === 0) name = "Sheet1"; | ||||
| 	return { pos:pos, hs:hidden, dt:dt, name:name }; | ||||
| } | ||||
| @ -425,8 +408,8 @@ function write_Font(data, opts) { | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLS] 2.4.149 */ | ||||
| function parse_LabelSst(blob, length, opts) { | ||||
| 	var cell = parse_XLSCell(blob, length, opts); | ||||
| function parse_LabelSst(blob) { | ||||
| 	var cell = parse_XLSCell(blob); | ||||
| 	cell.isst = blob.read_shift(4); | ||||
| 	return cell; | ||||
| } | ||||
| @ -441,7 +424,8 @@ 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, length, opts); | ||||
| 	var cell = parse_XLSCell(blob, 6); | ||||
| 	if(opts.biff == 2) blob.l++; | ||||
| 	var str = parse_XLUnicodeString(blob, target - blob.l, opts); | ||||
| 	cell.val = str; | ||||
| 	return cell; | ||||
| @ -475,19 +459,6 @@ 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) { | ||||
| @ -611,44 +582,6 @@ 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) { | ||||
| @ -669,7 +602,8 @@ function write_Guts(guts/*:Array<number>*/) { | ||||
| 
 | ||||
| /* [MS-XLS] 2.4.24 */ | ||||
| function parse_BoolErr(blob, length, opts) { | ||||
| 	var cell = parse_XLSCell(blob, 6, opts); | ||||
| 	var cell = parse_XLSCell(blob, 6); | ||||
| 	if(opts.biff == 2 || length == 9) ++blob.l; | ||||
| 	var val = parse_Bes(blob, 2); | ||||
| 	cell.val = val; | ||||
| 	cell.t = (val === true || val === false) ? 'b' : 'e'; | ||||
| @ -685,7 +619,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, opts); | ||||
| 	var cell = parse_XLSCell(blob, 6); | ||||
| 	var xnum = parse_Xnum(blob, 8); | ||||
| 	cell.val = xnum; | ||||
| 	return cell; | ||||
| @ -762,11 +696,9 @@ function parse_Lbl(blob, length, opts) { | ||||
| 	}; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLS] 2.4.106 TODO: legacy record filename encoding */ | ||||
| /* [MS-XLS] 2.4.106 TODO: verify 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];
 | ||||
| @ -818,34 +750,21 @@ function parse_MTRSettings(blob) { | ||||
| 	return [fMTREnabled, fUserSetThreadCount, cUserThreadCount]; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLS] 2.5.186 */ | ||||
| /* [MS-XLS] 2.5.186 TODO: BIFF5 */ | ||||
| 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>*/ { | ||||
| @ -1095,50 +1014,43 @@ 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, 7, opts); | ||||
| 	var cell = parse_XLSCell(blob, 6); | ||||
| 	++blob.l; | ||||
| 	var str = parse_XLUnicodeString2(blob, length-7, opts); | ||||
| 	cell.t = 'str'; | ||||
| 	cell.val = str; | ||||
| 	return cell; | ||||
| } | ||||
| 
 | ||||
| function parse_BIFF2NUM(blob, length, opts) { | ||||
| 	var cell = parse_XLSCell(blob, 7, opts); | ||||
| function parse_BIFF2NUM(blob/*::, length*/) { | ||||
| 	var cell = parse_XLSCell(blob, 6); | ||||
| 	++blob.l; | ||||
| 	var num = parse_Xnum(blob, 8); | ||||
| 	cell.t = 'n'; | ||||
| 	cell.val = num; | ||||
| 	return cell; | ||||
| } | ||||
| function write_BIFF2NUM(r/*:number*/, c/*:number*/, val/*:number*/, ixfe, ifmt) { | ||||
| function write_BIFF2NUM(r/*:number*/, c/*:number*/, val/*:number*/) { | ||||
| 	var out = new_buf(15); | ||||
| 	write_BIFF2Cell(out, r, c, ixfe||0, ifmt||0); | ||||
| 	write_BIFF2Cell(out, r, c); | ||||
| 	out.write_shift(8, val, 'f'); | ||||
| 	return out; | ||||
| } | ||||
| 
 | ||||
| function parse_BIFF2INT(blob, length, opts) { | ||||
| 	var cell = parse_XLSCell(blob, 7, opts); | ||||
| function parse_BIFF2INT(blob) { | ||||
| 	var cell = parse_XLSCell(blob, 6); | ||||
| 	++blob.l; | ||||
| 	var num = blob.read_shift(2); | ||||
| 	cell.t = 'n'; | ||||
| 	cell.val = num; | ||||
| 	return cell; | ||||
| } | ||||
| function write_BIFF2INT(r/*:number*/, c/*:number*/, val/*:number*/, ixfe/*:number*/, ifmt/*:number*/) { | ||||
| function write_BIFF2INT(r/*:number*/, c/*:number*/, val/*:number*/) { | ||||
| 	var out = new_buf(9); | ||||
| 	write_BIFF2Cell(out, r, c, ixfe||0, ifmt||0); | ||||
| 	write_BIFF2Cell(out, r, c); | ||||
| 	out.write_shift(2, val); | ||||
| 	return out; | ||||
| } | ||||
| @ -1149,16 +1061,6 @@ 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
 | ||||
| @ -1172,7 +1074,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, opts); | ||||
| 	var cell = parse_XLSCell(blob, 6); | ||||
| 	var cch = blob.read_shift(2); | ||||
| 	var str = parse_XLUnicodeStringNoCch(blob, cch, opts); | ||||
| 	blob.l = end; | ||||
| @ -1180,10 +1082,3 @@ 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 }; | ||||
| } | ||||
							
								
								
									
										410
									
								
								bits/40_harb.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										410
									
								
								bits/40_harb.js
									
									
									
									
									
								
							| @ -1,61 +1,62 @@ | ||||
| /* 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*/ { | ||||
| @ -118,7 +119,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][\S\s]*$/g,""); | ||||
| 		field.name = (typeof $cptable !== "undefined" ? $cptable.utils.decode(current_cp, d.slice(d.l, d.l+ww)) : a2s(d.slice(d.l, d.l + ww))).replace(/[\u0000\r\n].*$/g,""); | ||||
| 		d.l += ww; | ||||
| 		field.type = String.fromCharCode(d.read_shift(1)); | ||||
| 		if(ft != 0x02 && !l7) field.offset = d.read_shift(4); | ||||
| @ -176,13 +177,10 @@ 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])\s+$/,"$1"); | ||||
| 					if(s.trim().length) out[R][C] = s.replace(/\s+$/,""); | ||||
| 					break; | ||||
| 				case 'D': | ||||
| 					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]); } | ||||
| 					} | ||||
| 					if(s.length === 8) out[R][C] = new Date(+s.slice(0,4), +s.slice(4,6)-1, +s.slice(6,8)); | ||||
| 					else out[R][C] = s; | ||||
| 					break; | ||||
| 				case 'F': out[R][C] = parseFloat(s.trim()); break; | ||||
| @ -190,7 +188,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 '\x00': case '?': break; | ||||
| 					case '': case '?': break; | ||||
| 					default: throw new Error("DBF Unrecognized L:|" + s + "|"); | ||||
| 					} break; | ||||
| 				case 'M': /* TODO: handle memo files */ | ||||
| @ -205,12 +203,7 @@ 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': { | ||||
| 					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 'T': out[R][C] = new Date((dd.read_shift(4) - 0x253D8C) * 0x5265C00 + dd.read_shift(4)); break; | ||||
| 				case 'Y': out[R][C] = dd.read_shift(4,'i')/1e4 + (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; } | ||||
| @ -246,15 +239,14 @@ 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(); | ||||
| @ -290,8 +282,7 @@ function sheet_to_dbf(ws/*:Worksheet*/, opts/*:WriteOpts*/) { | ||||
| 				case 'object': _guess = col[j] instanceof Date ? 'D' : 'C'; break; | ||||
| 				default: _guess = 'C'; | ||||
| 			} | ||||
| 			/* TODO: cache the values instead of encoding twice */ | ||||
| 			maxlen = Math.max(maxlen, (typeof $cptable !== "undefined" && typeof col[j] == "string" ? $cptable.utils.encode(current_ansi, col[j]): String(col[j])).length); | ||||
| 			maxlen = Math.max(maxlen, String(col[j]).length); | ||||
| 			guess = guess && guess != _guess ? 'C' : _guess; | ||||
| 			//if(guess == 'C') break;
 | ||||
| 		} | ||||
| @ -317,17 +308,11 @@ 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); | ||||
| 	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; | ||||
| 	} | ||||
| 	h.write_shift(4, 0x00000000 | ((+dbf_reverse_map[/*::String(*/current_ansi/*::)*/] || 0x03)<<8)); | ||||
| 
 | ||||
| 	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"); | ||||
| @ -356,7 +341,6 @@ 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; | ||||
| @ -368,16 +352,13 @@ 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, "cpstr"); | ||||
| 					_l += colwidths[j] - rout.l; | ||||
| 					for(hcnt=0; hcnt < _l; ++hcnt) rout.write_shift(1, 0x20); break; | ||||
| 					rout.write_shift(1, _s, "sbcs"); | ||||
| 					for(hcnt=0; hcnt < colwidths[j]-_s.length; ++hcnt) rout.write_shift(1, 0x20); break; | ||||
| 			} | ||||
| 		} | ||||
| 		// data
 | ||||
| 	} | ||||
| 	current_codepage = old_cp; | ||||
| 	ba.next(1).write_shift(1, 0x1A); | ||||
| 	return ba.end(); | ||||
| } | ||||
| @ -404,21 +385,16 @@ 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").replace("{", "\\{") + "|\\|)", "gm"); | ||||
| 	try { | ||||
| 		sylk_char_regex = new RegExp("\u001BN(" + keys(sylk_escapes).join("|").replace(/\|\|\|/, "|\\||").replace(/([?()+])/g,"\\$1") + "|\\|)", "gm"); | ||||
| 	} catch(e) {} | ||||
| 	var sylk_char_regex = new RegExp("\u001BN(" + keys(sylk_escapes).join("|").replace(/\|\|\|/, "|\\||").replace(/([?()+])/g,"\\$1") + "|\\|)", "gm"); | ||||
| 	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) { | ||||
| @ -471,9 +447,8 @@ 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': cmnt = record[rj].slice(1); break; // TODO: comment
 | ||||
| 				case 'A': 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; | ||||
| @ -483,12 +458,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 = typeof val == "number" ? "n" : "d"; | ||||
| 						} | ||||
| 						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(typeof $cptable !== 'undefined' && typeof val == "string" && ((opts||{}).type != "string") && (opts||{}).codepage) val = $cptable.utils.decode(opts.codepage, val); | ||||
| 					C_seen_K = true; | ||||
| @ -524,10 +499,6 @@ 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; | ||||
| @ -589,27 +560,20 @@ var SYLK = /*#__PURE__*/(function() { | ||||
| 		return outwb; | ||||
| 	} | ||||
| 
 | ||||
| 	function write_ws_cell_sylk(cell/*:Cell*/, ws/*:Worksheet*/, R/*:number*/, C/*:number*/, opts, date1904/*:boolean*/)/*:string*/ { | ||||
| 	function write_ws_cell_sylk(cell/*:Cell*/, ws/*:Worksheet*/, R/*:number*/, C/*:number*//*::, opts*/)/*:string*/ { | ||||
| 		var o = "C;Y" + (R+1) + ";X" + (C+1) + ";K"; | ||||
| 		switch(cell.t) { | ||||
| 			case 'n': | ||||
| 				o += isFinite(cell.v) ? (cell.v||0) : BErr[isNaN(cell.v) ? 0x24 : 0x07]; | ||||
| 				o += (cell.v||0); | ||||
| 				if(cell.f && !cell.F) o += ";E" + a1_to_rc(cell.f, {r:R, c:C}); break; | ||||
| 			case 'b': o += cell.v ? "TRUE" : "FALSE"; break; | ||||
| 			case 'e': o += cell.w || 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; | ||||
| 			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; | ||||
| 		} | ||||
| 		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) + " "; | ||||
| @ -634,52 +598,29 @@ 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']||"A1"), cell/*:Cell*/; | ||||
| 		var dense = ws["!data"] != null; | ||||
| 		var r = safe_decode_range(ws['!ref']), cell/*:Cell*/; | ||||
| 		var dense = Array.isArray(ws); | ||||
| 		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']); | ||||
| 
 | ||||
| 		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("B;Y" + (r.e.r - r.s.r + 1) + ";X" + (r.e.c - r.s.c + 1) + ";D" + [r.s.c,r.s.r,r.e.c,r.e.r].join(" ")); | ||||
| 		preamble.push("O;L;D;B" + (d1904 ? ";V4" : "") + ";K47;G100 0.001"); | ||||
| 
 | ||||
| 		delete opts._formats; | ||||
| 		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)); | ||||
| 		} | ||||
| 		return preamble.join(RS) + RS + o.join(RS) + RS + "E" + RS; | ||||
| 	} | ||||
| 
 | ||||
| @ -719,10 +660,7 @@ 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); | ||||
| 						if(!(opts && opts.UTC)) { arr[R][C] = utc_to_local(arr[R][C]); } | ||||
| 					} | ||||
| 					else if(!isNaN(fuzzydate(value).getDate())) arr[R][C] = parseDate(value); | ||||
| 					else arr[R][C] = value; | ||||
| 					++C; break; | ||||
| 				case 1: | ||||
| @ -745,56 +683,62 @@ var DIF = /*#__PURE__*/(function() { | ||||
| 		return o; | ||||
| 	} | ||||
| 
 | ||||
| 	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\"\""); | ||||
| 	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, ""); | ||||
| 					} | ||||
| 				} | ||||
| 				p += "\r\n"; | ||||
| 			} | ||||
| 			o.push(p); | ||||
| 		} | ||||
| 		return o.join("") + "-1,0\r\nEOD"; | ||||
| 	} | ||||
| 			push_value(o, -1, 0, "EOD"); | ||||
| 			var RS = "\r\n"; | ||||
| 			var oo = o.join(RS); | ||||
| 			//while((oo.length & 0x7F) != 0) oo += "\0";
 | ||||
| 			return oo; | ||||
| 		}; | ||||
| 	})(); | ||||
| 	return { | ||||
| 		to_workbook: dif_to_workbook, | ||||
| 		to_sheet: dif_to_sheet, | ||||
| @ -822,7 +766,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[record.length-1].charAt(0) == "#" ? ({t: "e", v: RBErr[record[record.length-1]] }) : +record[4]; break; | ||||
| 						default: arr[R][C] = +record[4]; break; | ||||
| 					} | ||||
| 					if(record[2] == 'vtf') arr[R][C] = [arr[R][C], _f]; | ||||
| 			} | ||||
| @ -857,15 +801,19 @@ 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 = ws["!data"] != null; | ||||
| 		var dense = Array.isArray(ws); | ||||
| 		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["!data"][R]||[])[C] : ws[coord]; | ||||
| 				cell = dense ? (ws[R]||[])[C] : ws[coord]; | ||||
| 				if(!cell || cell.v == null || cell.t === 'z') continue; | ||||
| 				oo = ["cell", coord, 't']; | ||||
| 				switch(cell.t) { | ||||
| 					case 's': oo.push(encode(cell.v)); break; | ||||
| 					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 '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')); | ||||
| @ -875,19 +823,6 @@ 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(":")); | ||||
| @ -919,7 +854,6 @@ 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; | ||||
| 	} | ||||
| 
 | ||||
| @ -951,18 +885,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) { | ||||
| @ -993,8 +927,7 @@ var PRN = /*#__PURE__*/(function() { | ||||
| 		var o = opts || {}; | ||||
| 		var sep = ""; | ||||
| 		if(DENSE != null && o.dense == null) o.dense = DENSE; | ||||
| 		var ws/*:Worksheet*/ = ({}/*:any*/); | ||||
| 		if(o.dense) ws["!data"] = []; | ||||
| 		var ws/*:Worksheet*/ = o.dense ? ([]/*:any*/) : ({}/*:any*/); | ||||
| 		var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:0, r:0}}/*:any*/); | ||||
| 
 | ||||
| 		if(str.slice(0,4) == "sep=") { | ||||
| @ -1014,37 +947,33 @@ 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 = 's'; cell.f = s.slice(1); cell.v = s; } | ||||
| 				else if(fuzzyfmla(s)) { cell.t = 'n'; cell.f = s.slice(1); } | ||||
| 				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'; cell.v = v; } | ||||
| 			else if(!isNaN(v = fuzzynum(s))) { cell.t = 'n'; if(o.cellText !== false) cell.w = s; cell.v = v; } | ||||
| 			else if(!isNaN((v = fuzzydate(s)).getDate()) || _re && s.match(_re)) { | ||||
| 				cell.z = o.dateNF || table_fmt[14]; | ||||
| 				if(_re && s.match(_re)){ var news=dateNF_fix(s, o.dateNF, (s.match(_re)||[])); v = parseDate(news); if(o && o.UTC === false) v = utc_to_local(v); } | ||||
| 				else if(o && o.UTC === false) v = utc_to_local(v); | ||||
| 				else if(o.cellText !== false && o.dateNF) cell.w = SSF_format(cell.z, v); | ||||
| 				var k = 0; | ||||
| 				if(_re && s.match(_re)){ s=dateNF_fix(s, o.dateNF, (s.match(_re)||[])); k=1; v = parseDate(s, k); } | ||||
| 				if(o.cellDates) { cell.t = 'd'; cell.v = v; } | ||||
| 				else { cell.t = 'n'; cell.v = datenum(v); } | ||||
| 				if(o.cellText !== false) cell.w = SSF_format(cell.z, cell.v instanceof Date ? datenum(cell.v):cell.v); | ||||
| 				if(!o.cellNF) delete cell.z; | ||||
| 			} else 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["!data"][R]) ws["!data"][R] = []; ws["!data"][R][C] = cell; } | ||||
| 			else if(o.dense) { if(!ws[R]) ws[R] = []; ws[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; | ||||
| @ -1099,14 +1028,13 @@ 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 = ws["!data"] != null; | ||||
| 		var dense = Array.isArray(ws); | ||||
| 		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["!data"][R]||[])[C] : ws[coord]; | ||||
| 				cell = dense ? (ws[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 += " "; | ||||
| @ -1133,7 +1061,7 @@ function read_wb_ID(d, opts) { | ||||
| 		return out; | ||||
| 	} catch(e) { | ||||
| 		o.WTF = OLD_WTF; | ||||
| 		if((e.message.indexOf("SYLK bad record ID") == -1) && OLD_WTF) throw e; | ||||
| 		if(!e.message.match(/SYLK bad record ID/) && OLD_WTF) throw e; | ||||
| 		return PRN.to_workbook(d, opts); | ||||
| 	} | ||||
| } | ||||
|  | ||||
							
								
								
									
										593
									
								
								bits/41_lotus.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										593
									
								
								bits/41_lotus.js
									
									
									
									
									
								
							| @ -24,33 +24,15 @@ 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*/ = ({}/*:any*/), n = "Sheet1", next_n = "", sidx = 0; | ||||
| 		var sheets = {}, snames = [], realnames = [], sdata = []; | ||||
| 		if(o.dense) sdata = s["!data"] = []; | ||||
| 		var s/*:Worksheet*/ = ((o.dense ? [] : {})/*:any*/), n = "Sheet1", next_n = "", sidx = 0; | ||||
| 		var sheets = {}, snames = [], realnames = []; | ||||
| 
 | ||||
| 		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) { | ||||
| @ -82,9 +64,9 @@ var WK_ = /*#__PURE__*/(function() { | ||||
| 				case 0x0E: /* NUMBER */ | ||||
| 				case 0x10: /* FORMULA */ | ||||
| 					/* TODO: actual translation of the format code */ | ||||
| 					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(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(o.qpro) { | ||||
| @ -92,36 +74,26 @@ var WK_ = /*#__PURE__*/(function() { | ||||
| 							s["!ref"] = encode_range(refguess); | ||||
| 							sheets[n] = s; | ||||
| 							snames.push(n); | ||||
| 							s = ({}/*:any*/); if(o.dense) sdata = s["!data"] = []; | ||||
| 							s = (o.dense ? [] : {}); | ||||
| 							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 ? (sdata[val[0].r]||[])[val[0].c] : s[encode_cell(val[0])]; | ||||
| 					var tmpcell = o.dense ? (s[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(!sdata[val[0].r]) sdata[val[0].r] = []; | ||||
| 						sdata[val[0].r][val[0].c] = val[1]; | ||||
| 						if(!s[val[0].r]) s[val[0].r] = []; | ||||
| 						s[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; | ||||
| 				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; | ||||
| 				default: | ||||
| 			}}, o); | ||||
| 		} else if(d[2] == 0x1A || d[2] == 0x0E) { | ||||
| 			o.Enum = WK3Enum; | ||||
| @ -143,14 +115,14 @@ var WK_ = /*#__PURE__*/(function() { | ||||
| 						s["!ref"] = encode_range(refguess); | ||||
| 						sheets[n] = s; | ||||
| 						snames.push(n); | ||||
| 						s = ({}/*:any*/); if(o.dense) sdata = s["!data"] = []; | ||||
| 						s = (o.dense ? [] : {}); | ||||
| 						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(!sdata[val[0].r]) sdata[val[0].r] = []; | ||||
| 						sdata[val[0].r][val[0].c] = val[1]; | ||||
| 						if(!s[val[0].r]) s[val[0].r] = []; | ||||
| 						s[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; | ||||
| @ -184,32 +156,25 @@ 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 = ws["!data"] != null; | ||||
| 		var dense = Array.isArray(ws); | ||||
| 		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(C = range.s.c; C <= range.e.c; ++C) { | ||||
| 				var cell = dense ? (ws["!data"][R]||[])[C] : ws[cols[C] + rr]; | ||||
| 			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]; | ||||
| 				if(!cell || cell.t == "z") continue; | ||||
| 				/* TODO: formula records */ | ||||
| 				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: | ||||
| 				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 { | ||||
| 					var str = format_cell(cell); | ||||
| 					write_biff_rec(ba, 0x0F, write_LABEL(R, C, str.slice(0, 239))); | ||||
| 				} | ||||
| @ -235,7 +200,7 @@ var WK_ = /*#__PURE__*/(function() { | ||||
| 			var ws = wb.Sheets[wb.SheetNames[i]]; | ||||
| 			if(!ws || !ws["!ref"]) continue; | ||||
| 			var range = safe_decode_range(ws["!ref"]); | ||||
| 			var dense = ws["!data"] != null; | ||||
| 			var dense = Array.isArray(ws); | ||||
| 			var cols = []; | ||||
| 			var max_R = Math.min(range.e.r, 8191); | ||||
| 			for(var R = range.s.r; R <= max_R; ++R) { | ||||
| @ -243,7 +208,7 @@ var WK_ = /*#__PURE__*/(function() { | ||||
| 				for(var C = range.s.c; C <= range.e.c; ++C) { | ||||
| 					if(R === range.s.r) cols[C] = encode_col(C); | ||||
| 					var ref = cols[C] + rr; | ||||
| 					var cell = dense ? (ws["!data"][R]||[])[C] : ws[ref]; | ||||
| 					var cell = dense ? (ws[R]||[])[C] : ws[ref]; | ||||
| 					if(!cell || cell.t == "z") continue; | ||||
| 					/* TODO: FORMULA19 NUMBER18 records */ | ||||
| 					if(cell.t == "n") { | ||||
| @ -343,18 +308,11 @@ 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 & 0xFFFE) == 0x5120) { // WQ1 / WQ2
 | ||||
| 		if(opts.vers == 0x5120) { | ||||
| 			blob.l++; | ||||
| 			var len = blob.read_shift(1); | ||||
| 			o[1].v = blob.read_shift(len, 'utf8'); | ||||
| @ -396,12 +354,12 @@ var WK_ = /*#__PURE__*/(function() { | ||||
| 		o[1].v = blob.read_shift(2, 'i'); | ||||
| 		return o; | ||||
| 	} | ||||
| 	function write_INTEGER(R, C, cell) { | ||||
| 	function write_INTEGER(R, C, v) { | ||||
| 		var o = new_buf(7); | ||||
| 		o.write_shift(1, get_wk1_fmt(cell)); | ||||
| 		o.write_shift(1, 0xFF); | ||||
| 		o.write_shift(2, C); | ||||
| 		o.write_shift(2, R); | ||||
| 		o.write_shift(2, cell.v, 'i'); | ||||
| 		o.write_shift(2, v, 'i'); | ||||
| 		return o; | ||||
| 	} | ||||
| 
 | ||||
| @ -410,12 +368,12 @@ var WK_ = /*#__PURE__*/(function() { | ||||
| 		o[1].v = blob.read_shift(8, 'f'); | ||||
| 		return o; | ||||
| 	} | ||||
| 	function write_NUMBER(R, C, cell) { | ||||
| 	function write_NUMBER(R, C, v) { | ||||
| 		var o = new_buf(13); | ||||
| 		o.write_shift(1, get_wk1_fmt(cell)); | ||||
| 		o.write_shift(1, 0xFF); | ||||
| 		o.write_shift(2, C); | ||||
| 		o.write_shift(2, R); | ||||
| 		o.write_shift(8, cell.v, 'f'); | ||||
| 		o.write_shift(8, v, 'f'); | ||||
| 		return o; | ||||
| 	} | ||||
| 
 | ||||
| @ -468,7 +426,7 @@ var WK_ = /*#__PURE__*/(function() { | ||||
| 		0x33: ["FALSE", 0], | ||||
| 		0x34: ["TRUE", 0], | ||||
| 		0x35: ["RAND", 0], | ||||
| 		0x36: ["DATE", 3], | ||||
| 		// 0x36 DATE
 | ||||
| 		// 0x37 NOW
 | ||||
| 		// 0x38 PMT
 | ||||
| 		// 0x39 PV
 | ||||
| @ -478,7 +436,7 @@ var WK_ = /*#__PURE__*/(function() { | ||||
| 		// 0x3D MONTH
 | ||||
| 		// 0x3E YEAR
 | ||||
| 		0x3F: ["ROUND", 2], | ||||
| 		0x40: ["TIME", 3], | ||||
| 		// 0x40 TIME
 | ||||
| 		// 0x41 HOUR
 | ||||
| 		// 0x42 MINUTE
 | ||||
| 		// 0x43 SECOND
 | ||||
| @ -598,6 +556,7 @@ 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++]; | ||||
| @ -762,251 +721,209 @@ 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" }, | ||||
| 		// 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:"" } | ||||
| 		/*::[*/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:"" } | ||||
| 	}; | ||||
| 
 | ||||
| 	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*/ = ({}/*:any*/); if(o.dense) s["!data"] = []; | ||||
| 		var s/*:Worksheet*/ = ((o.dense ? [] : {})/*:any*/); | ||||
| 		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); | ||||
| @ -1017,22 +934,6 @@ 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; | ||||
| @ -1055,7 +956,7 @@ var WK_ = /*#__PURE__*/(function() { | ||||
| 
 | ||||
| 				case 0x0601: { /* BOS */ | ||||
| 					var sidx = p.read_shift(2); | ||||
| 					s = ({}/*:any*/); if(o.dense) s["!data"] = []; | ||||
| 					s = ((o.dense ? [] : {})/*:any*/); | ||||
| 					range.s.c = p.read_shift(2); | ||||
| 					range.e.c = p.read_shift(2); | ||||
| 					range.s.r = p.read_shift(4); | ||||
| @ -1092,28 +993,20 @@ 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), fmtidx = -1; | ||||
| 						if(flags & 0x80) fmtidx = p.read_shift(2); | ||||
| 						var flags = p.read_shift(1); | ||||
| 						if(flags & 0x80) p.l += 2; | ||||
| 						var mul = (flags & 0x40) ? p.read_shift(2) - 1: 0; | ||||
| 						switch(flags & 0x1F) { | ||||
| 							case 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; | ||||
| 								if(isNaN(cell.v)) cell = { t: "e", v: 0x0F }; // #VALUE!
 | ||||
| 								break; | ||||
| 							case 8: cell = { t: "n", v: p.read_shift(8, 'f') }; p.l += 2; /* cell.f = formulae[p.read_shift(4)]; */ p.l += 4; break; | ||||
| 							default: throw "Unrecognized QPW cell type " + (flags & 0x1F); | ||||
| 						} | ||||
| 						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; | ||||
| @ -1122,14 +1015,10 @@ var WK_ = /*#__PURE__*/(function() { | ||||
| 							default: throw "Unsupported delta for QPW cell type " + (flags & 0x1F); | ||||
| 						} | ||||
| 						if(!(!o.sheetStubs && cell.t == "z")) { | ||||
| 							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; | ||||
| 							if(Array.isArray(s)) { | ||||
| 								if(!s[R]) s[R] = []; | ||||
| 								s[R][C] = cell; | ||||
| 							} else s[encode_cell({r:R, c:C})] = cell; | ||||
| 						} | ||||
| 						++R; --cnt; | ||||
| 						while(mul-- > 0 && cnt >= 0) { | ||||
| @ -1144,29 +1033,17 @@ 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(s["!data"] != null) { | ||||
| 									if(!s["!data"][R]) s["!data"][R] = []; | ||||
| 									s["!data"][R][C] = cell; | ||||
| 								} else s[CC + encode_row(R)] = cell; | ||||
| 								if(Array.isArray(s)) { | ||||
| 									if(!s[R]) s[R] = []; | ||||
| 									s[R][C] = cell; | ||||
| 								} else s[encode_cell({r:R, c:C})] = 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,14 +107,15 @@ 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 = str_match_xml_ns(r, "t")/*, cp = 65001*/; | ||||
| 		var t = r.match(tregex)/*, cp = 65001*/; | ||||
| 		if(!t) return {t:"s", v:""}; | ||||
| 
 | ||||
| 		var o/*:Cell*/ = ({t:'s', v:unescapexml(t[1])}/*:any*/); | ||||
| 		var rpr = str_match_xml_ns(r, "rPr"); | ||||
| 		var rpr = r.match(rpregex); | ||||
| 		if(rpr) o.s = parse_rpr(rpr[1]); | ||||
| 		return o; | ||||
| 	} | ||||
| @ -167,7 +168,8 @@ var rs_to_html = /*#__PURE__*/(function parse_rs_factory() { | ||||
| })(); | ||||
| 
 | ||||
| /* 18.4.8 si CT_Rst */ | ||||
| var sitregex = /<(?:\w+:)?t\b[^<>]*>([^<]*)<\/(?:\w+:)?t>/g, sirregex = /<(?:\w+:)?r\b[^<>]*>/; | ||||
| var sitregex = /<(?:\w+:)?t[^>]*>([^<]*)<\/(?:\w+:)?t>/g, sirregex = /<(?:\w+:)?r>/; | ||||
| var sirphregex = /<(?:\w+:)?rPh.*?>([\s\S]*?)<\/(?:\w+:)?rPh>/g; | ||||
| function parse_si(x, opts) { | ||||
| 	var html = opts ? opts.cellHTML : true; | ||||
| 	var z = {}; | ||||
| @ -183,7 +185,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((str_remove_xml_ns_g(x, "rPh").match(sitregex)||[]).join("").replace(tagregex,"")), true); | ||||
| 		z.t = unescapexml(utf8read((x.replace(sirphregex, '').match(sitregex)||[]).join("").replace(tagregex,"")), true); | ||||
| 		if(html) z.h = rs_to_html(parse_rs(z.r)); | ||||
| 	} | ||||
| 	/* 18.4.3 phoneticPr CT_PhoneticPr (TODO: needed for Asian support) */ | ||||
| @ -192,20 +194,21 @@ 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 = str_match_xml_ns(data, "sst"); | ||||
| 	var sst = data.match(sstr0); | ||||
| 	if(sst) { | ||||
| 		ss = sst[1].replace(sstr1,"").split(sstr2); | ||||
| 		ss = sst[2].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[0].slice(0, sst[0].indexOf(">"))); s.Count = sst.count; s.Unique = sst.uniqueCount; | ||||
| 		sst = parsexmltag(sst[1]); s.Count = sst.count; s.Unique = sst.uniqueCount; | ||||
| 	} | ||||
| 	return s; | ||||
| } | ||||
| @ -226,7 +229,6 @@ 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,18 +13,14 @@ function rtf_to_sheet(d, opts) { | ||||
| } | ||||
| function rtf_to_sheet_str(str, opts) { | ||||
|   var o = opts || {}; | ||||
|   var ws = {}; | ||||
|   var dense = o.dense; | ||||
|   if (dense) | ||||
|     ws["!data"] = []; | ||||
|   var rows = str_match_ng(str, "\\trowd", "\\row"); | ||||
|   var ws = o.dense ? [] : {}; | ||||
|   var rows = str.match(/\\trowd[\s\S]*?\\row\b/g); | ||||
|   if (!rows) | ||||
|     throw new Error("RTF missing table"); | ||||
|   var range = { s: { c: 0, r: 0 }, e: { c: 0, r: rows.length - 1 } }; | ||||
|   var row = []; | ||||
|   rows.forEach(function(rowtf, R) { | ||||
|     if (dense) | ||||
|       row = ws["!data"][R] = []; | ||||
|     if (Array.isArray(ws)) | ||||
|       ws[R] = []; | ||||
|     var rtfre = /\\[\w\-]+\b/g; | ||||
|     var last_index = 0; | ||||
|     var res; | ||||
| @ -49,13 +45,9 @@ 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 (dense) | ||||
|               row[C] = cell; | ||||
|             if (Array.isArray(ws)) | ||||
|               ws[R][C] = cell; | ||||
|             else | ||||
|               ws[encode_cell({ r: R, c: C })] = cell; | ||||
|           } | ||||
| @ -83,17 +75,15 @@ function sheet_to_rtf(ws, opts) { | ||||
|   if (!ws["!ref"]) | ||||
|     return o[0] + "}"; | ||||
|   var r = safe_decode_range(ws["!ref"]), cell; | ||||
|   var dense = ws["!data"] != null, row = []; | ||||
|   var dense = Array.isArray(ws); | ||||
|   for (var R = r.s.r; R <= r.e.r; ++R) { | ||||
|     o.push("\\trowd\\trautofit1"); | ||||
|     for (var C = r.s.c; C <= r.e.c; ++C) | ||||
|       o.push("\\cellx" + (C + 1)); | ||||
|     o.push("\\pard\\intbl"); | ||||
|     if (dense) | ||||
|       row = ws["!data"][R] || []; | ||||
|     for (C = r.s.c; C <= r.e.c; ++C) { | ||||
|       var coord = encode_cell({ r: R, c: C }); | ||||
|       cell = dense ? row[C] : ws[coord]; | ||||
|       cell = dense ? (ws[R] || [])[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.match(tagregex)||[]).forEach(function(x) { | ||||
| 	(t[0].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.match(tagregex)||[]).forEach(function(x) { | ||||
| 	(t[0].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.match(tagregex)||[]).forEach(function(x) { | ||||
| 	(t[0].match(tagregex)||[]).forEach(function(x) { | ||||
| 		var y = parsexmltag(x); | ||||
| 		switch(strip_ns(y[0])) { | ||||
| 			case '<fonts': case '<fonts>': case '</fonts>': break; | ||||
| @ -163,12 +163,10 @@ 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': | ||||
| @ -180,55 +178,48 @@ 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>': case '</sz': break; | ||||
| 			case '<sz/>': case '</sz>': break; | ||||
| 
 | ||||
| 			/* 18.4.14 vertAlign CT_VerticalAlignFontProperty */ | ||||
| 			case '<vertAlign': if(y.val) font.vertAlign = y.val; break; | ||||
| 			case '<vertAlign/>': case '</vertAlign>': case '</vertAlign': break; | ||||
| 			case '<vertAlign/>': case '</vertAlign>': break; | ||||
| 
 | ||||
| 			/* 18.8.18 family CT_FontFamily */ | ||||
| 			case '<family': if(y.val) font.family = parseInt(y.val,10); break; | ||||
| 			case '<family/>': case '</family>': case '</family': break; | ||||
| 			case '<family/>': case '</family>': break; | ||||
| 
 | ||||
| 			/* 18.8.35 scheme CT_FontScheme */ | ||||
| 			case '<scheme': if(y.val) font.scheme = y.val; break; | ||||
| 			case '<scheme/>': case '</scheme>': case '</scheme': break; | ||||
| 			case '<scheme/>': case '</scheme>': break; | ||||
| 
 | ||||
| 			/* 18.4.1 charset CT_IntProperty */ | ||||
| 			case '<charset': | ||||
| 				if(y.val == '1') break; | ||||
| 				y.codepage = CS2CP[parseInt(y.val, 10)]; | ||||
| 				break; | ||||
| 			case '<charset/>': case '</charset>': case '</charset': break; | ||||
| 
 | ||||
| 			/* 18.?.? color CT_Color */ | ||||
| 			case '<color': | ||||
| @ -251,11 +242,11 @@ function parse_fonts(t, styles, themes, opts) { | ||||
| 				} | ||||
| 
 | ||||
| 				break; | ||||
| 			case '<color/>': case '</color>': case '</color': break; | ||||
| 			case '<color/>': case '</color>': break; | ||||
| 
 | ||||
| 			/* note: sometimes mc:AlternateContent appears bare */ | ||||
| 			case '<AlternateContent': pass = true; break; | ||||
| 			case '</AlternateContent>': case '</AlternateContent': pass = false; break; | ||||
| 			case '</AlternateContent>': pass = false; break; | ||||
| 
 | ||||
| 			/* 18.2.10 extLst CT_ExtensionList ? */ | ||||
| 			case '<extLst': case '<extLst>': case '</extLst>': break; | ||||
| @ -273,7 +264,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.match(tagregex); | ||||
| 	var m = t[0].match(tagregex); | ||||
| 	if(!m) return; | ||||
| 	for(i=0; i < m.length; ++i) { | ||||
| 		var y = parsexmltag(m[i]); | ||||
| @ -314,13 +305,13 @@ function parse_cellXfs(t, styles, opts) { | ||||
| 	styles.CellXf = []; | ||||
| 	var xf; | ||||
| 	var pass = false; | ||||
| 	(t.match(tagregex)||[]).forEach(function(x) { | ||||
| 	(t[0].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]]) | ||||
| @ -334,7 +325,7 @@ function parse_cellXfs(t, styles, opts) { | ||||
| 			case '</xf>': break; | ||||
| 
 | ||||
| 			/* 18.8.1 alignment CT_CellAlignment */ | ||||
| 			case '<alignment': case '<alignment/>': case '<alignment>': | ||||
| 			case '<alignment': case '<alignment/>': | ||||
| 				var alignment = {}; | ||||
| 				if(y.vertical) alignment.vertical = y.vertical; | ||||
| 				if(y.horizontal) alignment.horizontal = y.horizontal; | ||||
| @ -346,12 +337,12 @@ function parse_cellXfs(t, styles, opts) { | ||||
| 			case '</alignment>': break; | ||||
| 
 | ||||
| 			/* 18.8.33 protection CT_CellProtection */ | ||||
| 			case '<protection': case '<protection>': | ||||
| 			case '<protection': | ||||
| 				break; | ||||
| 			case '</protection>': case '<protection/>': break; | ||||
| 
 | ||||
| 			/* note: sometimes mc:AlternateContent appears bare */ | ||||
| 			case '<AlternateContent': case '<AlternateContent>': pass = true; break; | ||||
| 			case '<AlternateContent': pass = true; break; | ||||
| 			case '</AlternateContent>': pass = false; break; | ||||
| 
 | ||||
| 			/* 18.2.10 extLst CT_ExtensionList ? */ | ||||
| @ -379,31 +370,36 @@ 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 = remove_doctype(str_remove_ng(data, "<!--", "-->")); | ||||
| 	data = data.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,""); | ||||
| 	/* 18.8.39 styleSheet CT_Stylesheet */ | ||||
| 	var t; | ||||
| 
 | ||||
| 	/* 18.8.31 numFmts CT_NumFmts ? */ | ||||
| 	if((t=str_match_xml_ns(data, "numFmts"))) parse_numFmts(t[0], styles, opts); | ||||
| 	if((t=data.match(numFmtRegex))) parse_numFmts(t, styles, opts); | ||||
| 
 | ||||
| 	/* 18.8.23 fonts CT_Fonts ? */ | ||||
| 	if((t=str_match_xml_ns(data, "fonts"))) parse_fonts(t[0], styles, themes, opts); | ||||
| 	if((t=data.match(fontsRegex))) parse_fonts(t, styles, themes, opts); | ||||
| 
 | ||||
| 	/* 18.8.21 fills CT_Fills ? */ | ||||
| 	if((t=str_match_xml_ns(data, "fills"))) parse_fills(t[0], styles, themes, opts); | ||||
| 	if((t=data.match(fillsRegex))) parse_fills(t, styles, themes, opts); | ||||
| 
 | ||||
| 	/* 18.8.5  borders CT_Borders ? */ | ||||
| 	if((t=str_match_xml_ns(data, "borders"))) parse_borders(t[0], styles, themes, opts); | ||||
| 	if((t=data.match(bordersRegex))) parse_borders(t, styles, themes, opts); | ||||
| 
 | ||||
| 	/* 18.8.9  cellStyleXfs CT_CellStyleXfs ? */ | ||||
| 	/* 18.8.8  cellStyles CT_CellStyles ? */ | ||||
| 
 | ||||
| 	/* 18.8.10 cellXfs CT_CellXfs ? */ | ||||
| 	if((t=str_match_xml_ns(data, "cellXfs"))) parse_cellXfs(t[0], styles, opts); | ||||
| 	if((t=data.match(cellXfRegex))) parse_cellXfs(t, styles, opts); | ||||
| 
 | ||||
| 	/* 18.8.15 dxfs CT_Dxfs ? */ | ||||
| 	/* 18.8.42 tableStyles CT_TableStyles ? */ | ||||
|  | ||||
| @ -18,12 +18,10 @@ function parse_clrScheme(t, themes, opts) { | ||||
| 			/* 20.1.2.3.32 srgbClr CT_SRgbColor */ | ||||
| 			case '<a:srgbClr': | ||||
| 				color.rgb = y.val; break; | ||||
| 			case '</a:srgbClr>': break; | ||||
| 
 | ||||
| 			/* 20.1.2.3.33 sysClr CT_SystemColor */ | ||||
| 			case '<a:sysClr': | ||||
| 				color.rgb = y.lastClr; break; | ||||
| 			case '</a:sysClr>': break; | ||||
| 
 | ||||
| 			/* 20.1.4.1.1 accent1 (Accent 1) */ | ||||
| 			/* 20.1.4.1.2 accent2 (Accent 2) */ | ||||
| @ -37,10 +35,8 @@ 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:lt1>': | ||||
| 			case '<a:dk1>': | ||||
| 			case '<a:lt1>': | ||||
| 			case '<a:dk1>': case '</a:dk1>': | ||||
| 			case '<a:lt1>': case '</a:lt1>': | ||||
| 			case '<a:dk2>': case '</a:dk2>': | ||||
| 			case '<a:lt2>': case '</a:lt2>': | ||||
| 			case '<a:accent1>': case '</a:accent1>': | ||||
| @ -70,25 +66,31 @@ 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 */ | ||||
| 	if(!(t=str_match_xml(data, "a:clrScheme"))) throw new Error('clrScheme not found in themeElements'); | ||||
| 	parse_clrScheme(t, themes, opts); | ||||
| 
 | ||||
| 	/* 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); | ||||
| 	[ | ||||
| 		/* 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); | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| var themeltregex = /<a:themeElements([^>]*)>[\s\S]*<\/a:themeElements>/; | ||||
| 
 | ||||
| /* 14.2.7 Theme Part */ | ||||
| function parse_theme_xml(data/*:string*/, opts) { | ||||
| 	/* 20.1.6.9 theme CT_OfficeStyleSheet */ | ||||
| @ -98,7 +100,7 @@ function parse_theme_xml(data/*:string*/, opts) { | ||||
| 	var themes = {}; | ||||
| 
 | ||||
| 	/* themeElements CT_BaseStyles */ | ||||
| 	if(!(t=str_match_xml(data, "a:themeElements"))) throw new Error('themeElements not found in theme'); | ||||
| 	if(!(t=data.match(themeltregex))) 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 == null ? void 0 : opts.WTF)) | ||||
|         if (!pass && 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,42 +1,5 @@ | ||||
| /* L.5.5.2 SpreadsheetML Comments + VML Schema */ | ||||
| function parse_vml(data/*:string*/, sheet, comments) { | ||||
| 	var cidx = 0; | ||||
| 	(str_match_xml_ns_g(data, "shape")||[]).forEach(function(m) { | ||||
| 		var type = ""; | ||||
| 		var hidden = true; | ||||
| 		var aidx = -1; | ||||
| 		var R = -1, C = -1; | ||||
| 		m.replace(tagregex, function(x/*:string*/, idx/*:number*/) { | ||||
| 			var y = parsexmltag(x); | ||||
| 			switch(strip_ns(y[0])) { | ||||
| 				case '<ClientData': if(y.ObjectType) type = y.ObjectType; break; | ||||
| 
 | ||||
| 				case '<Visible': case '<Visible/>': hidden = false; break; | ||||
| 
 | ||||
| 				case '<Row': case '<Row>': aidx = idx + x.length; break; | ||||
| 				case '</Row>': R = +m.slice(aidx, idx).trim(); break; | ||||
| 
 | ||||
| 				case '<Column': case '<Column>': aidx = idx + x.length; break; | ||||
| 				case '</Column>': C = +m.slice(aidx, idx).trim(); break; | ||||
| 			} | ||||
| 			return ""; | ||||
| 		}); | ||||
| 		switch(type) { | ||||
| 		case 'Note': | ||||
| 			var cell = ws_get_cell_stub(sheet, ((R>=0 && C>=0) ? encode_cell({r:R,c:C}) : comments[cidx].ref)); | ||||
| 			if(cell.c) { | ||||
| 				cell.c.hidden = hidden; | ||||
| 			} | ||||
| 			++cidx; | ||||
| 			break; | ||||
| 		} | ||||
| 
 | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* comment boxes */ | ||||
| function write_vml(rId/*:number*/, comments, ws) { | ||||
| function write_vml(rId/*:number*/, comments) { | ||||
| 	var csize = [21600, 21600]; | ||||
| 	/* L.5.2.1.2 Path Attribute */ | ||||
| 	var bbox = ["m0,0l0",csize[1],csize[0],csize[1],csize[0],"0xe"].join(","); | ||||
| @ -58,7 +21,7 @@ function write_vml(rId/*:number*/, comments, ws) { | ||||
| 	return o.join(""); | ||||
| } | ||||
| 
 | ||||
| function write_vml_comment(x, _shapeid, ws)/*:string*/ { | ||||
| function write_vml_comment(x, _shapeid)/*:string*/ { | ||||
| 	var c = decode_cell(x[0]); | ||||
| 	var fillopts = /*::(*/{'color2':"#BEFF82", 'type':"gradient"}/*:: :any)*/; | ||||
| 	if(fillopts.type == "gradient") fillopts.angle = "-180"; | ||||
|  | ||||
| @ -1,16 +1,15 @@ | ||||
| function sheet_insert_comments(sheet/*:WorkSheet*/, comments/*:Array<RawComment>*/, threaded/*:boolean*/, people/*:?Array<any>*/) { | ||||
| 	var dense = sheet["!data"] != null; | ||||
| function sheet_insert_comments(sheet, comments/*:Array<RawComment>*/, threaded/*:boolean*/, people/*:?Array<any>*/) { | ||||
| 	var dense = Array.isArray(sheet); | ||||
| 	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["!data"][r.r]) sheet["!data"][r.r] = []; | ||||
| 			cell = sheet["!data"][r.r][r.c]; | ||||
| 			if(!sheet[r.r]) sheet[r.r] = []; | ||||
| 			cell = sheet[r.r][r.c]; | ||||
| 		} else cell = sheet[comment.ref]; | ||||
| 		if (!cell) { | ||||
| 			cell = ({t:"z"}/*:any*/); | ||||
| 			if(dense) sheet["!data"][r.r][r.c] = cell; | ||||
| 			if(dense) sheet[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; | ||||
| @ -18,7 +17,7 @@ function sheet_insert_comments(sheet/*:WorkSheet*/, comments/*:Array<RawComment> | ||||
| 			if(range.s.c > r.c) range.s.c = r.c; | ||||
| 			if(range.e.c < r.c) range.e.c = r.c; | ||||
| 			var encoded = encode_range(range); | ||||
| 			sheet["!ref"] = encoded; | ||||
| 			if (encoded !== sheet["!ref"]) sheet["!ref"] = encoded; | ||||
| 		} | ||||
| 
 | ||||
| 		if (!cell.c) cell.c = []; | ||||
| @ -36,3 +35,4 @@ function sheet_insert_comments(sheet/*:WorkSheet*/, comments/*:Array<RawComment> | ||||
| 		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 = str_match_xml_ns(data, "authors"); | ||||
| 	var authtag = data.match(/<(?:\w+:)?authors>([\s\S]*)<\/(?:\w+:)?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 = str_match_xml_ns(data, "commentList"); | ||||
| 	var cmnttag = data.match(/<(?:\w+:)?commentList>([\s\S]*)<\/(?:\w+:)?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 = str_match_xml_ns(x, "text"); | ||||
| 		var textMatch = x.match(/<(?:\w+:)?text>([\s\S]*)<\/(?:\w+:)?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,28 +50,21 @@ function write_comments_xml(data/*::, opts*/) { | ||||
| 	o.push("<commentList>"); | ||||
| 	data.forEach(function(d) { | ||||
| 		/* 18.7.3 CT_Comment */ | ||||
| 		var lastauthor = 0, ts = [], tcnt = 0; | ||||
| 		var lastauthor = 0, ts = []; | ||||
| 		if(d[1][0] && d[1][0].T && d[1][0].ID) lastauthor = iauthor.indexOf("tc=" + d[1][0].ID); | ||||
| 		d[1].forEach(function(c) { | ||||
| 		else d[1].forEach(function(c) { | ||||
| 			if(c.a) lastauthor = iauthor.indexOf(escapexml(c.a)); | ||||
| 			if(c.T) ++tcnt; | ||||
| 			ts.push(c.t == null ? "" : escapexml(c.t)); | ||||
| 			ts.push(c.t||""); | ||||
| 		}); | ||||
| 		if(tcnt === 0) { | ||||
| 			d[1].forEach(function(c) { | ||||
| 				o.push('<comment ref="' + d[0] + '" authorId="' + iauthor.indexOf(escapexml(c.a)) + '"><text>'); | ||||
| 				o.push(writetag("t", c.t == null ? "" : escapexml(c.t))); | ||||
| 				o.push('</text></comment>'); | ||||
| 			}); | ||||
| 		} else { | ||||
| 			if(d[1][0] && d[1][0].T && d[1][0].ID) lastauthor = iauthor.indexOf("tc=" + d[1][0].ID); | ||||
| 		o.push('<comment ref="' + d[0] + '" authorId="' + lastauthor + '"><text>'); | ||||
| 		if(ts.length <= 1) o.push(writetag("t", escapexml(ts[0]||""))); | ||||
| 		else { | ||||
| 			/* based on Threaded Comments -> Comments projection */ | ||||
| 			o.push('<comment ref="' + d[0] + '" authorId="' + lastauthor + '"><text>'); | ||||
| 			var t = "Comment:\n    " + (ts[0]) + "\n"; | ||||
| 			for(var i = 1; i < ts.length; ++i) t += "Reply:\n    " + ts[i] + "\n"; | ||||
| 			o.push(writetag("t", escapexml(t))); | ||||
| 			o.push('</text></comment>'); | ||||
| 		} | ||||
| 		o.push('</text></comment>'); | ||||
| 	}); | ||||
| 	o.push("</commentList>"); | ||||
| 	if(o.length>2) { o[o.length] = ('</comments>'); o[1]=o[1].replace("/>",">"); } | ||||
|  | ||||
| @ -74,10 +74,6 @@ 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 */); | ||||
| @ -85,11 +81,7 @@ function write_comments_bin(data/*::, opts*/) { | ||||
| 	write_record(ba, 0x0279 /* BrtBeginCommentList */); | ||||
| 	data.forEach(function(comment) { | ||||
| 		comment[1].forEach(function(c) { | ||||
| 			var _ia = -1; | ||||
| 			if(c.ID) _ia = iauthor.indexOf("tc=" + c.ID); | ||||
| 			if(_ia == -1 && comment[1][0].T && comment[1][0].ID) _ia = iauthor.indexOf("tc=" + comment[1][0].ID); | ||||
| 			if(_ia == -1) _ia = iauthor.indexOf(c.a); | ||||
| 			c.iauthor = _ia; | ||||
| 			c.iauthor = iauthor.indexOf(c.a); | ||||
| 			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,10 +23,7 @@ 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])(\$?)(\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 crefregex = /(^|[^._A-Z0-9])([$]?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])([$]?)(10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})(?![_.\(A-Za-z0-9])/g; | ||||
| var a1_to_rc = /*#__PURE__*/(function(){ | ||||
| 	return function a1_to_rc(fstr/*:string*/, base/*:CellAddress*/) { | ||||
| 		return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5) { | ||||
|  | ||||
							
								
								
									
										196
									
								
								bits/62_fxls.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										196
									
								
								bits/62_fxls.js
									
									
									
									
									
								
							| @ -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,7 +68,8 @@ 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, opts); | ||||
| 	var cell = parse_XLSCell(blob, 6); | ||||
| 	if(opts.biff == 2) ++blob.l; | ||||
| 	var val = parse_FormulaValue(blob,8); | ||||
| 	var flags = blob.read_shift(1); | ||||
| 	if(opts.biff != 2) { | ||||
| @ -262,7 +263,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(":"); | ||||
| 	var parts = _str.split(":"); str = parts[0]; | ||||
| 
 | ||||
| 	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(/!/,".").replace(/:/, ":."); | ||||
| 	return r.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, date1904) { | ||||
| function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, themes, styles) { | ||||
| 	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, !!date1904); | ||||
| 				var dd = datenum(p.v); | ||||
| 				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, !!date1904),_ssfopts); | ||||
| 		else if(p.t === 'd') p.w = SSF_format(fmtid,datenum(p.v),_ssfopts); | ||||
| 		else p.w = SSF_format(fmtid,p.v,_ssfopts); | ||||
| 	} catch(e) { if(opts.WTF) throw e; } | ||||
| 	if(!opts.cellStyles) return; | ||||
|  | ||||
							
								
								
									
										153
									
								
								bits/67_wsxml.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										153
									
								
								bits/67_wsxml.js
									
									
									
									
									
								
							| @ -2,13 +2,16 @@ 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 hlinkregex = /<(?:\w+:)?hyperlink [^<>]*>/mg; | ||||
| var mergecregex = /<(?:\w:)?mergeCell ref="[A-Z0-9:]+"\s*[\/]?>/g; | ||||
| var sheetdataregex = /<(?:\w+:)?sheetData[^>]*>([\s\S]*)<\/(?:\w+:)?sheetData>/; | ||||
| var hlinkregex = /<(?:\w:)?hyperlink [^>]*>/mg; | ||||
| var dimregex = /"(\w*:\w*)"/; | ||||
| var colregex = /<(?:\w+:)?col\b[^<>]*[\/]?>/g; | ||||
| var afregex = /<(?:\w+:)?autoFilter[^>]*/g; | ||||
| var marginregex= /<(?:\w+:)?pageMargins[^<>]*\/>/g; | ||||
| var sheetprregex = /<(?:\w+:)?sheetPr\b[^<>]*?\/>/; | ||||
| 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)>/; | ||||
| 
 | ||||
| /* 18.3 Worksheets */ | ||||
| function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBProps*/, themes, styles)/*:Worksheet*/ { | ||||
| @ -17,11 +20,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 = ({}/*:any*/); if(opts.dense) s["!data"] = []; | ||||
| 	var s = opts.dense ? ([]/*:any*/) : ({}/*:any*/); | ||||
| 	var refguess/*:Range*/ = ({s: {r:2000000, c:2000000}, e: {r:0, c:0} }/*:any*/); | ||||
| 
 | ||||
| 	var data1 = "", data2 = ""; | ||||
| 	var mtch/*:?any*/ = str_match_xml_ns(data, "sheetData"); | ||||
| 	var mtch/*:?any*/ = data.match(sheetdataregex); | ||||
| 	if(mtch) { | ||||
| 		data1 = data.slice(0, mtch.index); | ||||
| 		data2 = data.slice(mtch.index + mtch[0].length); | ||||
| @ -30,17 +33,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 = str_match_xml_ns(data1, "sheetPr"))) parse_ws_xml_sheetpr2(sheetPr[0], sheetPr[1]||"", s, wb, idx, styles, themes); | ||||
| 	else if((sheetPr = data1.match(sheetprregex2))) 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 && !(opts && opts.nodim)) parse_ws_xml_dim(s, ref[1]); | ||||
| 		if(ref) parse_ws_xml_dim(s, ref[1]); | ||||
| 	} | ||||
| 
 | ||||
| 	/* 18.3.1.88 sheetViews CT_SheetViews */ | ||||
| 	var svs = str_match_xml_ns(data1, "sheetViews"); | ||||
| 	var svs = data1.match(svsregex); | ||||
| 	if(svs && svs[1]) parse_ws_xml_sheetviews(svs[1], wb); | ||||
| 
 | ||||
| 	/* 18.3.1.17 cols CT_Cols */ | ||||
| @ -52,7 +55,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, wb); | ||||
| 	if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles); | ||||
| 
 | ||||
| 	/* 18.3.1.2  autoFilter CT_AutoFilter */ | ||||
| 	var afilter = data2.match(afregex); | ||||
| @ -62,7 +65,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("=")+2)); | ||||
| 		merges[ridx] = safe_decode_range(_merge[ridx].slice(_merge[ridx].indexOf("\"")+1)); | ||||
| 
 | ||||
| 	/* 18.3.1.48 hyperlinks CT_Hyperlinks */ | ||||
| 	var hlink = data2.match(hlinkregex); | ||||
| @ -72,11 +75,6 @@ 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"]); | ||||
| @ -92,7 +90,6 @@ 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; | ||||
| } | ||||
| 
 | ||||
| @ -152,7 +149,7 @@ function write_ws_xml_protection(sp)/*:string*/ { | ||||
| } | ||||
| 
 | ||||
| function parse_ws_xml_hlinks(s, data/*:Array<string>*/, rels) { | ||||
| 	var dense = s["!data"] != null; | ||||
| 	var dense = Array.isArray(s); | ||||
| 	for(var i = 0; i != data.length; ++i) { | ||||
| 		var val = parsexmltag(utf8read(data[i]), true); | ||||
| 		if(!val.ref) return; | ||||
| @ -168,11 +165,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_col(C) + encode_row(R); | ||||
| 			var addr = encode_cell({c:C,r:R}); | ||||
| 			if(dense) { | ||||
| 				if(!s["!data"][R]) s["!data"][R] = []; | ||||
| 				if(!s["!data"][R][C]) s["!data"][R][C] = {t:"z",v:undefined}; | ||||
| 				s["!data"][R][C].l = val; | ||||
| 				if(!s[R]) s[R] = []; | ||||
| 				if(!s[R][C]) s[R][C] = {t:"z",v:undefined}; | ||||
| 				s[R][C].l = val; | ||||
| 			} else { | ||||
| 				if(!s[addr]) s[addr] = {t:"z",v:undefined}; | ||||
| 				s[addr].l = val; | ||||
| @ -239,7 +236,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*/) { | ||||
| @ -259,27 +256,21 @@ 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, date1904)/*:string*/ { | ||||
| function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts/*::, idx, wb*/)/*: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': | ||||
| 			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 'n': vv = ''+cell.v; break; | ||||
| 		case 'e': vv = BErr[cell.v]; break; | ||||
| 		case 'd': | ||||
| 			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 { | ||||
| 			if(opts && opts.cellDates) vv = parseDate(cell.v, -1).toISOString(); | ||||
| 			else { | ||||
| 				cell = dup(cell); | ||||
| 				cell.t = 'n'; | ||||
| 				vv = ''+(cell.v = datenum(parseDate(cell.v, date1904), date1904)); | ||||
| 				vv = ''+(cell.v = datenum(parseDate(cell.v))); | ||||
| 			} | ||||
| 			if(typeof cell.z === 'undefined') cell.z = table_fmt[14]; | ||||
| 			break; | ||||
| @ -308,20 +299,18 @@ function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts, idx, wb, date1904)/*:st | ||||
| 		var ff = cell.F && cell.F.slice(0, ref.length) == ref ? {t:"array", ref:cell.F} : null; | ||||
| 		v = writextag('f', escapexml(cell.f), ff) + (cell.v != null ? v : ""); | ||||
| 	} | ||||
| 	if(cell.l) { | ||||
| 		cell.l.display = escapexml(vv); | ||||
| 		ws['!links'].push([ref, cell.l]); | ||||
| 	} | ||||
| 	if(cell.l) 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=["']([^"']*)["']/; | ||||
| 	var rregex = /r=["']([^"']*)["']/, isregex = /<(?:\w+:)?is>([\S\s]*?)<\/(?:\w+:)?is>/; | ||||
| 	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, wb) { | ||||
| return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, themes, styles) { | ||||
| 	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; | ||||
| @ -329,10 +318,9 @@ 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 = s["!data"] != null; | ||||
| 	var dense = Array.isArray(s); | ||||
| 	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; | ||||
| @ -361,10 +349,8 @@ 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(!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(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; | ||||
| @ -398,31 +384,23 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th | ||||
| 			d = x.slice(i); | ||||
| 			p = ({t:""}/*:any*/); | ||||
| 
 | ||||
| 			if((cref=str_match_xml_ns(d, "v"))!= null && /*::cref != null && */cref[1] !== '') p.v=unescapexml(cref[1]); | ||||
| 			if((cref=d.match(match_v))!= null && /*::cref != null && */cref[1] !== '') p.v=unescapexml(cref[1]); | ||||
| 			if(opts.cellFormula) { | ||||
| 				if((cref=str_match_xml_ns(d, "f"))!= null /*:: && cref != null*/) { | ||||
| 					if(cref[1] == "") { | ||||
| 						if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="shared"') > -1) { | ||||
| 							// TODO: parse formula
 | ||||
| 							ftag = parsexmltag(cref[0]); | ||||
| 							if(sharedf[ftag.si]) p.f = shift_formula_xlsx(sharedf[ftag.si][1], sharedf[ftag.si][2]/*[0].ref*/, tag.r); | ||||
| 						} | ||||
| 					} else { | ||||
| 						/* TODO: match against XLSXFutureFunctions */ | ||||
| 						p.f=unescapexml(utf8read(cref[1]), true); | ||||
| 						if(!opts.xlfn) p.f = _xlfn(p.f); | ||||
| 						if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="array"') > -1) { | ||||
| 							p.F = (d.match(refregex)||[])[1]; | ||||
| 							if(p.F.indexOf(":") > -1) arrayf.push([safe_decode_range(p.F), p.F]); | ||||
| 						} else if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="shared"') > -1) { | ||||
| 							// TODO: parse formula
 | ||||
| 							ftag = parsexmltag(cref[0]); | ||||
| 							var ___f = unescapexml(utf8read(cref[1])); | ||||
| 							if(!opts.xlfn) ___f = _xlfn(___f); | ||||
| 							sharedf[parseInt(ftag.si, 10)] = [ftag, ___f, tag.r]; | ||||
| 						} | ||||
| 				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]; | ||||
| 					} | ||||
| 				} 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); | ||||
| 				} | ||||
| @ -468,7 +446,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 = str_match_xml_ns(d, "is"); | ||||
| 					cref = d.match(isregex); | ||||
| 					p.t = 's'; | ||||
| 					if(cref != null && (sstr = parse_si(cref[1]))) { | ||||
| 						p.v = sstr.t; | ||||
| @ -477,8 +455,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, date1904); | ||||
| 					else { p.v = datenum(parseDate(p.v, date1904), date1904); p.t = 'n'; } | ||||
| 					if(opts.cellDates) p.v = parseDate(p.v, 1); | ||||
| 					else { p.v = datenum(parseDate(p.v, 1)); p.t = 'n'; } | ||||
| 					break; | ||||
| 				/* error string in .w, number in .v */ | ||||
| 				case 'e': | ||||
| @ -497,22 +475,16 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			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'; } | ||||
| 			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); } | ||||
| 			if(tag.cm && opts.xlmeta) { | ||||
| 				var cm = (opts.xlmeta.Cell||[])[+tag.cm-1]; | ||||
| 				if(cm && cm.type == 'XLDAPR') p.D = true; | ||||
| 			} | ||||
| 			var _r; | ||||
| 			if(opts.nodim) { | ||||
| 				_r = decode_cell(tag.r); | ||||
| 				if(guess.s.r > _r.r) guess.s.r = _r.r; | ||||
| 				if(guess.e.r < _r.r) guess.e.r = _r.r; | ||||
| 			} | ||||
| 			if(dense) { | ||||
| 				_r = decode_cell(tag.r); | ||||
| 				if(!s["!data"][_r.r]) s["!data"][_r.r] = []; | ||||
| 				s["!data"][_r.r][_r.c] = p; | ||||
| 				var _r = decode_cell(tag.r); | ||||
| 				if(!s[_r.r]) s[_r.r] = []; | ||||
| 				s[_r.r][_r.c] = p; | ||||
| 			} else s[tag.r] = p; | ||||
| 		} | ||||
| 	} | ||||
| @ -521,19 +493,17 @@ 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 = ws["!data"] != null, data = dense ? ws["!data"] : []; | ||||
| 	var dense = Array.isArray(ws); | ||||
| 	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); | ||||
| 		var data_R = dense ? data[R] : []; | ||||
| 		for(C = range.s.c; C <= range.e.c; ++C) { | ||||
| 			ref = cols[C] + rr; | ||||
| 			var _cell = dense ? data_R[C] : ws[ref]; | ||||
| 			var _cell = dense ? (ws[R]||[])[C]: ws[ref]; | ||||
| 			if(_cell === undefined) continue; | ||||
| 			if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb, date1904)) != null) r.push(cell); | ||||
| 			if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb)) != null) r.push(cell); | ||||
| 		} | ||||
| 		if(r.length > 0 || (rows && rows[R])) { | ||||
| 			params = ({r:rr}/*:any*/); | ||||
| @ -634,12 +604,11 @@ 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(/#[\s\S]*$/, ""), RELS.HLINK); | ||||
| 				rId = add_rels(rels, -1, escapexml(l[1].Target).replace(/#.*$/, ""), 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,13 +41,12 @@ 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 = dense ? (ws["!data"][caddr.r]||[])[caddr.c] : ws[encode_cell(caddr)]; | ||||
| 			var cell = Array.isArray(ws) ? (ws[caddr.r]||[])[caddr.c] : ws[encode_cell(caddr)]; | ||||
| 			if(cell) { if(first < 0) first = j; last = j; } | ||||
| 		} | ||||
| 		if(first < 0) continue; | ||||
| @ -259,10 +258,9 @@ 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(data, o); | ||||
| 	write_XLWideString(cell.v, o); | ||||
| 	return o.length > o.l ? o.slice(0, o.l) : o; | ||||
| } | ||||
| function parse_BrtShortSt(data) { | ||||
| @ -271,10 +269,9 @@ function parse_BrtShortSt(data) { | ||||
| 	return [cell, value, 'str']; | ||||
| } | ||||
| function write_BrtShortSt(cell, ncell, o) { | ||||
| 	var data = cell.v == null ? "" : String(cell.v); | ||||
| 	if(o == null) o = new_buf(8 + 4 * data.length); | ||||
| 	if(o == null) o = new_buf(8 + 4 * cell.v.length); | ||||
| 	write_XLSBShortCell(ncell, o); | ||||
| 	write_XLWideString(data, o); | ||||
| 	write_XLWideString(cell.v, o); | ||||
| 	return o.length > o.l ? o.slice(0, o.l) : o; | ||||
| } | ||||
| 
 | ||||
| @ -511,7 +508,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*/ = ({}); if(opts.dense) s["!data"] = []; | ||||
| 	var s/*:Worksheet*/ = (opts.dense ? [] : {}); | ||||
| 
 | ||||
| 	var ref; | ||||
| 	var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} }; | ||||
| @ -542,7 +539,6 @@ 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; | ||||
| @ -586,9 +582,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, date1904>0); | ||||
| 				if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.numFmtId,null,opts, themes, styles); | ||||
| 				C = val[0].c == -1 ? C + 1 : val[0].c; | ||||
| 				if(opts.dense) { if(!s["!data"][R]) s["!data"][R] = []; s["!data"][R][C] = p; } | ||||
| 				if(opts.dense) { if(!s[R]) s[R] = []; s[R][C] = p; } | ||||
| 				else s[encode_col(C) + rr] = p; | ||||
| 				if(opts.cellFormula) { | ||||
| 					af = false; | ||||
| @ -607,7 +603,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 + 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)); } | ||||
| 					var _d = SSF_parse_date_code(p.v); if(_d) { p.t = 'd'; p.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); } | ||||
| 				} | ||||
| 				if(cm) { | ||||
| 					if(cm.type == 'XLDAPR') p.D = true; | ||||
| @ -621,7 +617,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["!data"][R]) s["!data"][R] = []; s["!data"][R][C] = p; } | ||||
| 				if(opts.dense) { if(!s[R]) s[R] = []; s[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; | ||||
| @ -652,11 +648,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["!data"][R]) s["!data"][R] = []; | ||||
| 						if(!s["!data"][R][C]) s["!data"][R][C] = {t:'z',v:undefined}; | ||||
| 						s["!data"][R][C].l = val; | ||||
| 						if(!s[R]) s[R] = []; | ||||
| 						if(!s[R][C]) s[R][C] = {t:'z',v:undefined}; | ||||
| 						s[R][C].l = val; | ||||
| 					} else { | ||||
| 						addr = encode_col(C) + encode_row(R); | ||||
| 						addr = encode_cell({c:C,r:R}); | ||||
| 						if(!s[addr]) s[addr] = {t:'z',v:undefined}; | ||||
| 						s[addr].l = val; | ||||
| 					} | ||||
| @ -666,14 +662,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["!data"][R][C] : s[encode_col(C) + rr])/*:any*/); | ||||
| 				cell = ((opts.dense ? s[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["!data"][R][C] : s[encode_col(C) + rr]); | ||||
| 				cell = (opts.dense ? s[R][C] : s[encode_col(C) + rr]); | ||||
| 				cell.f = stringify_formula(val[1], refguess, {r:row.r, c:C}, supbooks, opts); | ||||
| 				break; | ||||
| 
 | ||||
| @ -687,10 +683,6 @@ 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; | ||||
| @ -747,6 +739,7 @@ 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' */ | ||||
| @ -805,12 +798,11 @@ 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*/, date1904/*:boolean*/)/*:boolean*/ { | ||||
| function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, ws/*:Worksheet*/, last_seen/*:boolean*/)/*:boolean*/ { | ||||
| 	var o/*:any*/ = ({r:R, c:C}/*:any*/); | ||||
| 	if(cell.c) ws['!comments'].push([encode_cell(o), cell.c]); | ||||
| 	if(cell.v === undefined) return false; | ||||
| @ -820,7 +812,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, date1904), date1904); cell.t = 'n'; | ||||
| 			cell.v = datenum(parseDate(cell.v)); cell.t = 'n'; | ||||
| 			break; | ||||
| 		/* falls through */ | ||||
| 		case 'n': case 'e': vv = ''+cell.v; break; | ||||
| @ -832,7 +824,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 == null ? "" : String(cell.v)/*:any*/), opts.revStrings); | ||||
| 				vv = get_sst_id(opts.Strings, (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)); | ||||
| @ -847,15 +839,6 @@ 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}, o)); // #NUM!
 | ||||
| 				} else { | ||||
| 					if(last_seen) write_record(ba, 0x000E /* BrtShortError */, write_BrtShortError({t:"e", v: 0x07}, o)); // #DIV/0!
 | ||||
| 					else write_record(ba, 0x0003 /* BrtCellError */, write_BrtCellError({t:"e", v: 0x07}, o)); // #DIV/0!
 | ||||
| 				} | ||||
| 			} else { | ||||
| 				if(last_seen) write_record(ba, 0x0010 /* BrtShortReal */, write_BrtShortReal(cell, o)); | ||||
| 				else write_record(ba, 0x0005 /* BrtCellReal */, write_BrtCellReal(cell, o)); | ||||
| @ -876,28 +859,26 @@ function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:num | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| function write_CELLTABLE(ba, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbook*/) { | ||||
| 	var range = safe_decode_range(ws['!ref'] || "A1"), rr = "", cols/*:Array<string>*/ = []; | ||||
| 	var date1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904; | ||||
| function write_CELLTABLE(ba, ws/*:Worksheet*/, idx/*:number*/, opts/*::, wb:Workbook*/) { | ||||
| 	var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols/*:Array<string>*/ = []; | ||||
| 	write_record(ba, 0x0091 /* BrtBeginSheetData */); | ||||
| 	var dense = ws["!data"] != null, row = dense ? ws["!data"][range.s.r] : []; | ||||
| 	var dense = Array.isArray(ws); | ||||
| 	var cap = range.e.r; | ||||
| 	if(ws['!rows']) cap = Math.max(range.e.r, ws['!rows'].length - 1); | ||||
| 	for(var R = range.s.r; R <= cap; ++R) { | ||||
| 		rr = encode_row(R); | ||||
| 		if(dense) row = ws["!data"][R]; | ||||
| 		/* [ACCELLTABLE] */ | ||||
| 		/* BrtRowHdr */ | ||||
| 		write_row_header(ba, ws, range, R); | ||||
| 		if(dense && !row) continue; | ||||
| 		var last_seen = false; | ||||
| 		if(R <= range.e.r) for(var C = range.s.c; C <= range.e.c; ++C) { | ||||
| 			/* *16384CELL */ | ||||
| 			if(R === range.s.r) cols[C] = encode_col(C); | ||||
| 			var cell = dense ? row[C] : ws[cols[C] + rr]; | ||||
| 			ref = cols[C] + rr; | ||||
| 			var cell = dense ? (ws[R]||[])[C] : ws[ref]; | ||||
| 			if(!cell) { last_seen = false; continue; } | ||||
| 			/* write cell */ | ||||
| 			last_seen = write_ws_bin_cell(ba, cell, R, C, opts, ws, last_seen, date1904); | ||||
| 			last_seen = write_ws_bin_cell(ba, cell, R, C, opts, ws, last_seen); | ||||
| 		} | ||||
| 	} | ||||
| 	write_record(ba, 0x0092 /* BrtEndSheetData */); | ||||
| @ -928,7 +909,7 @@ function write_HLINKS(ba, ws/*:Worksheet*/, rels) { | ||||
| 	/* *BrtHLink */ | ||||
| 	ws['!links'].forEach(function(l) { | ||||
| 		if(!l[1].Target) return; | ||||
| 		var rId = add_rels(rels, -1, l[1].Target.replace(/#[\s\S]*$/, ""), RELS.HLINK); | ||||
| 		var rId = add_rels(rels, -1, l[1].Target.replace(/#.*$/, ""), RELS.HLINK); | ||||
| 		write_record(ba, 0x01EE /* BrtHLink */, write_BrtHLink(l, rId)); | ||||
| 	}); | ||||
| 	delete ws['!links']; | ||||
|  | ||||
| @ -4,16 +4,16 @@ function parse_Cache(data/*:string*/)/*:[Array<number|string>, string, ?string]* | ||||
| 	var f; | ||||
| 
 | ||||
| 	/* 21.2.2.150 pt CT_NumVal */ | ||||
| 	(data.match(/<c:pt idx="(\d*)"[^<>\/]*><c:v>([^<])<\/c:v><\/c:pt>/mg)||[]).forEach(function(pt) { | ||||
| 		var q = pt.match(/<c:pt idx="(\d*)"[^<>\/]*><c:v>([^<]*)<\/c:v><\/c:pt>/); | ||||
| 	(data.match(/<c:pt idx="(\d*)">(.*?)<\/c:pt>/mg)||[]).forEach(function(pt) { | ||||
| 		var q = pt.match(/<c:pt idx="(\d*?)"><c:v>(.*)<\/c:v><\/c:pt>/); | ||||
| 		if(!q) return; | ||||
| 		col[+q[1]] = num ? +q[2] : q[2]; | ||||
| 	}); | ||||
| 
 | ||||
| 	/* 21.2.2.71 formatCode CT_Xstring */ | ||||
| 	var nf = unescapexml((str_match_xml(data, "c:formatCode") || ["","General"])[1]); | ||||
| 	var nf = unescapexml((data.match(/<c:formatCode>([\s\S]*?)<\/c:formatCode>/) || ["","General"])[1]); | ||||
| 
 | ||||
| 	(str_match_ng(data, "<c:f>", "</c:f>")||[]).forEach(function(F) { f = F.replace(/<[^<>]*>/g,""); }); | ||||
| 	(data.match(/<c:f>(.*?)<\/c:f>/mg)||[]).forEach(function(F) { f = F.replace(/<.*?>/g,""); }); | ||||
| 
 | ||||
| 	return [col, nf, f]; | ||||
| } | ||||
| @ -28,16 +28,13 @@ function parse_chart(data/*:?string*/, name/*:string*/, opts, rels, wb, csheet) | ||||
| 	var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} }; | ||||
| 
 | ||||
| 	/* 21.2.2.120 numCache CT_NumData */ | ||||
| 	(str_match_ng(data, "<c:numCache>", "</c:numCache>")||[]).forEach(function(nc) { | ||||
| 	(data.match(/<c:numCache>[\s\S]*?<\/c:numCache>/gm)||[]).forEach(function(nc) { | ||||
| 		var cache = parse_Cache(nc); | ||||
| 		refguess.s.r = refguess.s.c = 0; | ||||
| 		refguess.e.c = C; | ||||
| 		col = encode_col(C); | ||||
| 		cache[0].forEach(function(n,i) { | ||||
| 			if(cs["!data"]) { | ||||
| 				if(!cs["!data"][i]) cs["!data"][i] = []; | ||||
| 				cs["!data"][i][C] = {t:'n', v:n, z:cache[1] }; | ||||
| 			} else cs[col + encode_row(i)] = {t:'n', v:n, z:cache[1] }; | ||||
| 			cs[col + encode_row(i)] = {t:'n', v:n, z:cache[1] }; | ||||
| 			R = i; | ||||
| 		}); | ||||
| 		if(refguess.e.r < R) refguess.e.r = R; | ||||
|  | ||||
| @ -115,17 +115,14 @@ function safe1904(wb/*:Workbook*/)/*:string*/ { | ||||
| 
 | ||||
| var badchars = /*#__PURE__*/":][*?\/\\".split(""); | ||||
| function check_ws_name(n/*:string*/, safe/*:?boolean*/)/*:boolean*/ { | ||||
| 	try { | ||||
| 		if(n == "") throw new Error("Sheet name cannot be blank"); | ||||
| 		if(n.length > 31) throw new Error("Sheet name cannot exceed 31 chars"); | ||||
| 		if(n.charCodeAt(0) == 0x27 || n.charCodeAt(n.length - 1) == 0x27) throw new Error("Sheet name cannot start or end with apostrophe (')"); | ||||
| 		if(n.toLowerCase() == "history") throw new Error("Sheet name cannot be 'History'"); | ||||
| 		badchars.forEach(function(c) { | ||||
| 			if(n.indexOf(c) == -1) return; | ||||
| 			throw new Error("Sheet name cannot contain : \\ / ? * [ ]"); | ||||
| 		}); | ||||
| 	} catch(e) { if(safe) return false; throw e; } | ||||
| 	return true; | ||||
| 	if(n.length > 31) { if(safe) return false; throw new Error("Sheet names cannot exceed 31 chars"); } | ||||
| 	var _good = true; | ||||
| 	badchars.forEach(function(c) { | ||||
| 		if(n.indexOf(c) == -1) return; | ||||
| 		if(!safe) throw new Error("Sheet name cannot contain : \\ / ? * [ ]"); | ||||
| 		_good = false; | ||||
| 	}); | ||||
| 	return _good; | ||||
| } | ||||
| function check_wb_names(N, S, codes) { | ||||
| 	N.forEach(function(n,i) { | ||||
|  | ||||
| @ -69,14 +69,8 @@ function parse_BrtName(data, length, opts) { | ||||
| 	data.l += 1; //var chKey = data.read_shift(1);
 | ||||
| 	var itab = data.read_shift(4); | ||||
| 	var name = parse_XLNameWideString(data); | ||||
| 	var formula; | ||||
| 	var comment = ""; | ||||
| 	try { | ||||
| 		formula = parse_XLSBNameParsedFormula(data, 0, opts); | ||||
| 		try { | ||||
| 			comment = parse_XLNullableWideString(data); | ||||
| 		} catch(e){} | ||||
| 	} catch(e) { console.error("Could not parse defined name " + name); } | ||||
| 	var formula = parse_XLSBNameParsedFormula(data, 0, opts); | ||||
| 	var comment = parse_XLNullableWideString(data); | ||||
| 	if(flags & 0x20) name = "_xlnm." + name; | ||||
| 	//if(0 /* fProc */) {
 | ||||
| 		// unusedstring1: XLNullableWideString
 | ||||
| @ -147,7 +141,7 @@ function parse_wb_bin(data, opts)/*:WorkbookFile*/ { | ||||
| 
 | ||||
| 			case 0x0027: /* 'BrtName' */ | ||||
| 				if(val.Sheet != null) opts.SID = val.Sheet; | ||||
| 				val.Ref = val.Ptg ? stringify_formula(val.Ptg, null, null, supbooks, opts) : "#REF!"; | ||||
| 				val.Ref = stringify_formula(val.Ptg, null, null, supbooks, opts); | ||||
| 				delete opts.SID; | ||||
| 				delete val.Ptg; | ||||
| 				Names.push(val); | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| var attregexg2=/\b((?:\w+:)?[\w]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g; | ||||
| var attregex2=/\b((?:\w+:)?[\w]+)=((?:")(?:[^"]*)(?:")|(?:')(?:[^']*)(?:'))/; | ||||
| var attregexg2=/([\w:]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g; | ||||
| var attregex2=/([\w:]+)=((?:")(?:[^"]*)(?:")|(?:')(?:[^']*)(?:'))/; | ||||
| function xlml_parsexmltag(tag/*:string*/, skip_root/*:?boolean*/) { | ||||
| 	var words = tag.split(/\s+/); | ||||
| 	var z/*:any*/ = ([]/*:any*/); if(!skip_root) z[0] = words[0]; | ||||
| @ -40,10 +40,10 @@ function xlml_parsexmltagobj(tag/*:string*/) { | ||||
| /* map from xlml named formats to SSF TODO: localize */ | ||||
| var XLMLFormatMap/*: {[string]:string}*/; | ||||
| 
 | ||||
| function xlml_format(format, value, date1904)/*:string*/ { | ||||
| function xlml_format(format, value)/*:string*/ { | ||||
| 	var fmt = XLMLFormatMap[format] || unescapexml(format); | ||||
| 	if(fmt === "General") return SSF_general(value); | ||||
| 	return SSF_format(fmt, value, {date1904: !!date1904}); | ||||
| 	return SSF_format(fmt, value); | ||||
| } | ||||
| 
 | ||||
| function xlml_set_custprop(Custprops, key, cp, val/*:string*/) { | ||||
| @ -59,7 +59,7 @@ function xlml_set_custprop(Custprops, key, cp, val/*:string*/) { | ||||
| 	Custprops[unescapexml(key)] = oval; | ||||
| } | ||||
| 
 | ||||
| function safe_format_xlml(cell/*:Cell*/, nf, o, date1904) { | ||||
| function safe_format_xlml(cell/*:Cell*/, nf, o) { | ||||
| 	if(cell.t === 'z') return; | ||||
| 	if(!o || o.cellText !== false) try { | ||||
| 		if(cell.t === 'e') { cell.w = cell.w || BErr[cell.v]; } | ||||
| @ -70,13 +70,13 @@ function safe_format_xlml(cell/*:Cell*/, nf, o, date1904) { | ||||
| 			} | ||||
| 			else cell.w = SSF_general(cell.v); | ||||
| 		} | ||||
| 		else cell.w = xlml_format(nf||"General", cell.v, date1904); | ||||
| 		else cell.w = xlml_format(nf||"General", cell.v); | ||||
| 	} catch(e) { if(o.WTF) throw e; } | ||||
| 	try { | ||||
| 		var z = XLMLFormatMap[nf]||nf||"General"; | ||||
| 		if(o.cellNF) cell.z = z; | ||||
| 		if(o.cellDates && cell.t == 'n' && fmt_is_date(z)) { | ||||
| 			var _d = SSF_parse_date_code(cell.v + (date1904 ? 1462 : 0)); if(_d) { cell.t = 'd'; cell.v = new Date(Date.UTC(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u)); } | ||||
| 			var _d = SSF_parse_date_code(cell.v); if(_d) { cell.t = 'd'; cell.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); } | ||||
| 		} | ||||
| 	} catch(e) { if(o.WTF) throw e; } | ||||
| } | ||||
| @ -92,18 +92,17 @@ function process_style_xlml(styles, stag, opts) { | ||||
| } | ||||
| 
 | ||||
| /* TODO: there must exist some form of OSP-blessed spec */ | ||||
| function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, arrayf, o, date1904) { | ||||
| function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, arrayf, o) { | ||||
| 	var nf = "General", sid = cell.StyleID, S = {}; o = o || {}; | ||||
| 	var interiors = []; | ||||
| 	var i = 0; | ||||
| 	if(sid === undefined && row) sid = row.StyleID; | ||||
| 	if(sid === undefined && csty) sid = csty.StyleID; | ||||
| 	while(styles[sid] !== undefined) { | ||||
| 		var ssid = styles[sid]; | ||||
| 		if(ssid.nf) nf = ssid.nf; | ||||
| 		if(ssid.Interior) interiors.push(ssid.Interior); | ||||
| 		if(!ssid.Parent) break; | ||||
| 		sid = ssid.Parent; | ||||
| 		if(styles[sid].nf) nf = styles[sid].nf; | ||||
| 		if(styles[sid].Interior) interiors.push(styles[sid].Interior); | ||||
| 		if(!styles[sid].Parent) break; | ||||
| 		sid = styles[sid].Parent; | ||||
| 	} | ||||
| 	switch(data.Type) { | ||||
| 		case 'Boolean': | ||||
| @ -112,12 +111,13 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, a | ||||
| 			break; | ||||
| 		case 'String': | ||||
| 			cell.t = 's'; cell.r = xlml_fixstr(unescapexml(xml)); | ||||
| 			cell.v = (xml.indexOf("<") > -1 ? unescapexml(ss||xml).replace(/<[^<>]*>/g, "") : cell.r); // todo: BR etc
 | ||||
| 			cell.v = (xml.indexOf("<") > -1 ? unescapexml(ss||xml).replace(/<.*?>/g, "") : cell.r); // todo: BR etc
 | ||||
| 			break; | ||||
| 		case 'DateTime': | ||||
| 			if(xml.slice(-1) != "Z") xml += "Z"; | ||||
| 			cell.v = datenum(parseDate(xml, date1904), date1904); | ||||
| 			cell.v = (parseDate(xml) - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000); | ||||
| 			if(cell.v !== cell.v) cell.v = unescapexml(xml); | ||||
| 			else if(cell.v<60) cell.v = cell.v -1; | ||||
| 			if(!nf || nf == "General") nf = "yyyy-mm-dd"; | ||||
| 			/* falls through */ | ||||
| 		case 'Number': | ||||
| @ -130,7 +130,7 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, a | ||||
| 			else { cell.t = 's'; cell.v = xlml_fixstr(ss||xml); } | ||||
| 			break; | ||||
| 	} | ||||
| 	safe_format_xlml(cell, nf, o, date1904); | ||||
| 	safe_format_xlml(cell, nf, o); | ||||
| 	if(o.cellFormula !== false) { | ||||
| 		if(cell.Formula) { | ||||
| 			var fstr = unescapexml(cell.Formula); | ||||
| @ -207,7 +207,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ { | ||||
| 	var Rn; | ||||
| 	var state = [], tmp; | ||||
| 	if(DENSE != null && opts.dense == null) opts.dense = DENSE; | ||||
| 	var sheets = {}, sheetnames/*:Array<string>*/ = [], cursheet/*:Worksheet*/ = ({}), sheetname = ""; if(opts.dense) cursheet["!data"] = []; | ||||
| 	var sheets = {}, sheetnames/*:Array<string>*/ = [], cursheet/*:Worksheet*/ = (opts.dense ? [] : {}), sheetname = ""; | ||||
| 	var cell = ({}/*:any*/), row = {};// eslint-disable-line no-unused-vars
 | ||||
| 	var dtag = xlml_parsexmltag('<Data ss:Type="String">'), didx = 0; | ||||
| 	var c = 0, r = 0; | ||||
| @ -222,7 +222,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ { | ||||
| 	var rowinfo/*:Array<RowInfo>*/ = [], rowobj = {}, cc = 0, rr = 0; | ||||
| 	var Workbook/*:WBWBProps*/ = ({ Sheets:[], WBProps:{date1904:false} }/*:any*/), wsprops = {}; | ||||
| 	xlmlregex.lastIndex = 0; | ||||
| 	str = str_remove_ng(str, "<!--", "-->"); | ||||
| 	str = str.replace(/<!--([\s\S]*?)-->/mg,""); | ||||
| 	var raw_Rn3 = ""; | ||||
| 	while((Rn = xlmlregex.exec(str))) switch((Rn[3] = (raw_Rn3 = Rn[3]).toLowerCase())) { | ||||
| 		case 'data' /*case 'Data'*/: | ||||
| @ -232,7 +232,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ { | ||||
| 				break; | ||||
| 			} | ||||
| 			if(state[state.length-1][1]) break; | ||||
| 			if(Rn[1]==='/') parse_xlml_data(str.slice(didx, Rn.index), ss, dtag, state[state.length-1][0]==/*"Comment"*/"comment"?comment:cell, {c:c,r:r}, styles, cstys[c], row, arrayf, opts, Workbook.WBProps.date1904); | ||||
| 			if(Rn[1]==='/') parse_xlml_data(str.slice(didx, Rn.index), ss, dtag, state[state.length-1][0]==/*"Comment"*/"comment"?comment:cell, {c:c,r:r}, styles, cstys[c], row, arrayf, opts); | ||||
| 			else { ss = ""; dtag = xlml_parsexmltag(Rn[0]); didx = Rn.index + Rn[0].length; } | ||||
| 			break; | ||||
| 		case 'cell' /*case 'Cell'*/: | ||||
| @ -240,8 +240,8 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ { | ||||
| 				if(comments.length > 0) cell.c = comments; | ||||
| 				if((!opts.sheetRows || opts.sheetRows > r) && cell.v !== void 0) { | ||||
| 					if(opts.dense) { | ||||
| 						if(!cursheet["!data"][r]) cursheet["!data"][r] = []; | ||||
| 						cursheet["!data"][r][c] = cell; | ||||
| 						if(!cursheet[r]) cursheet[r] = []; | ||||
| 						cursheet[r][c] = cell; | ||||
| 					} else cursheet[encode_col(c) + encode_row(r)] = cell; | ||||
| 				} | ||||
| 				if(cell.HRef) { | ||||
| @ -261,8 +261,8 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ { | ||||
| 						for(var cmd = r; cmd <= rr; ++cmd) { | ||||
| 							if(cma > c || cmd > r) { | ||||
| 								if(opts.dense) { | ||||
| 									if(!cursheet["!data"][cmd]) cursheet["!data"][cmd] = []; | ||||
| 									cursheet["!data"][cmd][cma] = {t:'z'}; | ||||
| 									if(!cursheet[cmd]) cursheet[cmd] = []; | ||||
| 									cursheet[cmd][cma] = {t:'z'}; | ||||
| 								} else cursheet[encode_col(cma) + encode_row(cmd)] = {t:'z'}; | ||||
| 							} | ||||
| 						} | ||||
| @ -321,7 +321,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ { | ||||
| 				state.push([Rn[3], false]); | ||||
| 				tmp = xlml_parsexmltag(Rn[0]); | ||||
| 				sheetname = unescapexml(tmp.Name); | ||||
| 				cursheet = ({}); if(opts.dense) cursheet["!data"] = []; | ||||
| 				cursheet = (opts.dense ? [] : {}); | ||||
| 				merges = []; | ||||
| 				arrayf = []; | ||||
| 				rowinfo = []; | ||||
| @ -443,7 +443,6 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ { | ||||
| 			} else { | ||||
| 				state.push([Rn[3], false]); | ||||
| 				tmp = xlml_parsexmltag(Rn[0]); | ||||
| 				if(!parsexmlbool(tmp["ShowAlways"]||"0")) comments.hidden = true; | ||||
| 				comment = ({a:tmp.Author}/*:any*/); | ||||
| 			} | ||||
| 			break; | ||||
| @ -535,9 +534,6 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ { | ||||
| 						/*:: if(!Workbook.WBProps) Workbook.WBProps = {}; */ | ||||
| 						Workbook.WBProps.date1904 = true; | ||||
| 						break; | ||||
| 					case 'hidehorizontalscrollbar' /*case 'HideHorizontalScrollBar'*/: break; | ||||
| 					case 'hideverticalscrollbar' /*case 'HideVerticalScrollBar'*/: break; | ||||
| 					case 'hideworkbooktabs' /*case 'HideWorkbookTabs'*/: break; | ||||
| 					case 'windowheight' /*case 'WindowHeight'*/: break; | ||||
| 					case 'windowwidth' /*case 'WindowWidth'*/: break; | ||||
| 					case 'windowtopx' /*case 'WindowTopX'*/: break; | ||||
| @ -1106,15 +1102,11 @@ function write_ws_xlml_wsopts(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workb | ||||
| 	return writextag("WorksheetOptions", o.join(""), {xmlns:XLMLNS.x}); | ||||
| } | ||||
| function write_ws_xlml_comment(comments/*:Array<any>*/)/*:string*/ { | ||||
| 	/* TODO: test multiple comments */ | ||||
| 	return comments.map(function(c) { | ||||
| 		// TODO: formatted text
 | ||||
| 		var t = xlml_unfixstr(c.t||""); | ||||
| 		var d =writextag("ss:Data", t, {"xmlns":"http://www.w3.org/TR/REC-html40"}); | ||||
| 		var p = {}; | ||||
| 		if(c.a) p["ss:Author"] = c.a; | ||||
| 		if(!comments.hidden) p["ss:ShowAlways"] = "1"; | ||||
| 		return writextag("Comment", d, p); | ||||
| 		return writextag("Comment", d, {"ss:Author":c.a}); | ||||
| 	}).join(""); | ||||
| } | ||||
| function write_ws_xlml_cell(cell, ref/*:string*/, ws, opts, idx/*:number*/, wb, addr)/*:string*/{ | ||||
| @ -1144,13 +1136,7 @@ function write_ws_xlml_cell(cell, ref/*:string*/, ws, opts, idx/*:number*/, wb, | ||||
| 	var t = "", p = ""; | ||||
| 	switch(cell.t) { | ||||
| 		case 'z': if(!opts.sheetStubs) return ""; break; | ||||
| 		case 'n': { | ||||
| 			if(!isFinite(cell.v)) { | ||||
| 				t = 'Error'; p = BErr[isNaN(cell.v) ? 0x24 : 0x07]; | ||||
| 			} else { | ||||
| 				t = 'Number'; p = String(cell.v); | ||||
| 			} | ||||
| 		} break; | ||||
| 		case 'n': t = 'Number'; p = String(cell.v); break; | ||||
| 		case 'b': t = 'Boolean'; p = (cell.v ? "1" : "0"); break; | ||||
| 		case 'e': t = 'Error'; p = BErr[cell.v]; break; | ||||
| 		case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); if(cell.z == null) cell.z = cell.z || table_fmt[14]; break; | ||||
| @ -1191,13 +1177,10 @@ function write_ws_xlml_table(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbo | ||||
| 		if(n.hidden) k['ss:Hidden']="1"; | ||||
| 		o.push(writextag("Column",null,k)); | ||||
| 	}); | ||||
| 	var dense = ws["!data"] != null; | ||||
| 	var addr = {r:0,c:0}; | ||||
| 	var dense = Array.isArray(ws); | ||||
| 	for(var R = range.s.r; R <= range.e.r; ++R) { | ||||
| 		var row = [write_ws_xlml_row(R, (ws['!rows']||[])[R])]; | ||||
| 		addr.r = R; | ||||
| 		for(var C = range.s.c; C <= range.e.c; ++C) { | ||||
| 			addr.c = C; | ||||
| 			var skip = false; | ||||
| 			for(mi = 0; mi != marr.length; ++mi) { | ||||
| 				if(marr[mi].s.c > C) continue; | ||||
| @ -1208,7 +1191,8 @@ function write_ws_xlml_table(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbo | ||||
| 				break; | ||||
| 			} | ||||
| 			if(skip) continue; | ||||
| 			var ref = encode_col(C) + encode_row(R), cell = dense ? (ws["!data"][R]||[])[C] : ws[ref]; | ||||
| 			var addr = {r:R,c:C}; | ||||
| 			var ref = encode_cell(addr), cell = dense ? (ws[R]||[])[C] : ws[ref]; | ||||
| 			row.push(write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr)); | ||||
| 		} | ||||
| 		row.push("</Row>"); | ||||
| @ -1231,7 +1215,7 @@ function write_ws_xlml(idx/*:number*/, opts, wb/*:Workbook*/)/*:string*/ { | ||||
| 	/* WorksheetOptions */ | ||||
| 	o.push(write_ws_xlml_wsopts(ws, opts, idx, wb)); | ||||
| 
 | ||||
| 	if(ws && ws["!autofilter"]) o.push('<AutoFilter x:Range="' + a1_to_rc(fix_range(ws["!autofilter"].ref), {r:0,c:0}) + '" xmlns="urn:schemas-microsoft-com:office:excel"></AutoFilter>'); | ||||
| 	if(ws["!autofilter"]) o.push('<AutoFilter x:Range="' + a1_to_rc(fix_range(ws["!autofilter"].ref), {r:0,c:0}) + '" xmlns="urn:schemas-microsoft-com:office:excel"></AutoFilter>'); | ||||
| 
 | ||||
| 	return o.join(""); | ||||
| } | ||||
| @ -1250,10 +1234,11 @@ function write_xlml(wb, opts)/*:string*/ { | ||||
| 	d.push(write_props_xlml(wb, opts)); | ||||
| 	d.push(write_wb_xlml(wb, opts)); | ||||
| 	d.push(""); | ||||
| 	d.push(write_names_xlml(wb, opts)); | ||||
| 	d.push(""); | ||||
| 	for(var i = 0; i < wb.SheetNames.length; ++i) | ||||
| 		d.push(writextag("Worksheet", write_ws_xlml(i, opts, wb), {"ss:Name":escapexml(wb.SheetNames[i])})); | ||||
| 	d[2] = write_sty_xlml(wb, opts); | ||||
| 	d[3] = write_names_xlml(wb, opts); | ||||
| 	return XML_HEADER + writextag("Workbook", d.join(""), { | ||||
| 		'xmlns':      XLMLNS.ss, | ||||
| 		'xmlns:o':    XLMLNS.o, | ||||
|  | ||||
							
								
								
									
										109
									
								
								bits/76_xls.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										109
									
								
								bits/76_xls.js
									
									
									
									
									
								
							| @ -77,7 +77,7 @@ function safe_format_xf(p/*:any*/, opts/*:ParseOpts*/, date1904/*:?boolean*/) { | ||||
| 	var fmtid = 0; | ||||
| 	try { | ||||
| 		fmtid = p.z || p.XF.numFmtId || 0; | ||||
| 		if(opts.cellNF && p.z == null) p.z = table_fmt[fmtid]; | ||||
| 		if(opts.cellNF) p.z = table_fmt[fmtid]; | ||||
| 	} catch(e) { if(opts.WTF) throw e; } | ||||
| 	if(!opts || opts.cellText !== false) try { | ||||
| 		if(p.t === 'e') { p.w = p.w || BErr[p.v]; } | ||||
| @ -91,7 +91,7 @@ function safe_format_xf(p/*:any*/, opts/*:ParseOpts*/, date1904/*:?boolean*/) { | ||||
| 		else p.w = SSF_format(fmtid,p.v, {date1904:!!date1904, dateNF: opts && opts.dateNF}); | ||||
| 	} catch(e) { if(opts.WTF) throw e; } | ||||
| 	if(opts.cellDates && fmtid && p.t == 'n' && fmt_is_date(table_fmt[fmtid] || String(fmtid))) { | ||||
| 		var _d = SSF_parse_date_code(p.v + (date1904 ? 1462 : 0)); if(_d) { p.t = 'd'; p.v = new Date(Date.UTC(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u)); } | ||||
| 		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); } | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| @ -104,7 +104,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 	var wb = ({opts:{}}/*:any*/); | ||||
| 	var Sheets = {}; | ||||
| 	if(DENSE != null && options.dense == null) options.dense = DENSE; | ||||
| 	var out/*:Worksheet*/ = ({}/*:any*/); if(options.dense) out["!data"] = []; | ||||
| 	var out/*:Worksheet*/ = ((options.dense ? [] : {})/*:any*/); | ||||
| 	var Directory = {}; | ||||
| 	var range/*:Range*/ = ({}/*:any*/); | ||||
| 	var last_formula = null; | ||||
| @ -119,13 +119,12 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 	var XFs = []; /* XF records */ | ||||
| 	var palette/*:Array<[number, number, number]>*/ = []; | ||||
| 	var Workbook/*:WBWBProps*/ = ({ Sheets:[], WBProps:{date1904:false}, Views:[{}] }/*:any*/), wsprops = {}; | ||||
| 	var biff4w = false; | ||||
| 	var get_rgb = function getrgb(icv/*:number*/)/*:[number, number, number]*/ { | ||||
| 		if(icv < 8) return XLSIcv[icv]; | ||||
| 		if(icv < 64) return palette[icv-8] || XLSIcv[icv]; | ||||
| 		return XLSIcv[icv]; | ||||
| 	}; | ||||
| 	var process_cell_style = function pcs(line/*:any*/, options) { | ||||
| 	var process_cell_style = function pcs(cell, line/*:any*/, options) { | ||||
| 		var xfd = line.XF.data; | ||||
| 		if(!xfd || !xfd.patternType || !options || !options.cellStyles) return; | ||||
| 		line.s = ({}/*:any*/); | ||||
| @ -135,9 +134,9 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 		if((t = rgb2Hex(get_rgb(xfd.icvBack)))) { line.s.bgColor = {rgb:t}; } | ||||
| 	}; | ||||
| 	var addcell = function addcell(cell/*:any*/, line/*:any*/, options/*:any*/) { | ||||
| 		if(!biff4w && file_depth > 1) return; | ||||
| 		if(file_depth > 1) return; | ||||
| 		if(options.sheetRows && cell.r >= options.sheetRows) return; | ||||
| 		if(options.cellStyles && line.XF && line.XF.data) process_cell_style(line, options); | ||||
| 		if(options.cellStyles && line.XF && line.XF.data) process_cell_style(cell, line, options); | ||||
| 		delete line.ixfe; delete line.XF; | ||||
| 		lastcell = cell; | ||||
| 		last_cell = encode_cell(cell); | ||||
| @ -158,8 +157,8 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 		} | ||||
| 		{ | ||||
| 			if(options.dense) { | ||||
| 				if(!out["!data"][cell.r]) out["!data"][cell.r] = []; | ||||
| 				out["!data"][cell.r][cell.c] = line; | ||||
| 				if(!out[cell.r]) out[cell.r] = []; | ||||
| 				out[cell.r][cell.c] = line; | ||||
| 			} else out[last_cell] = line; | ||||
| 		} | ||||
| 	}; | ||||
| @ -205,7 +204,6 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 		if(RecordType === 0 && last_RT === 0x000a /* EOF */) break; | ||||
| 		var length = (blob.l === blob.length ? 0 : blob.read_shift(2)); | ||||
| 		var R = XLSRecordEnum[RecordType]; | ||||
| 		if(file_depth == 0 && [0x0009, 0x0209, 0x0409, 0x0809].indexOf(RecordType) == -1 /* BOF */) break; | ||||
| 		//console.log(RecordType.toString(16), RecordType, R, blob.l, length, blob.length);
 | ||||
| 		//if(!R) console.log(blob.slice(blob.l, blob.l + length));
 | ||||
| 		if(R && R.f) { | ||||
| @ -266,7 +264,6 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 					if(!val.fBelow) (out["!outline"] || (out["!outline"] = {})).above = true; | ||||
| 					if(!val.fRight) (out["!outline"] || (out["!outline"] = {})).left = true; | ||||
| 					break; // TODO
 | ||||
| 				case 0x0043: /* BIFF2XF */ case 0x0243: /* BIFF3XF */ case 0x0443: /* BIFF4XF */ | ||||
| 				case 0x00e0 /* XF */: | ||||
| 					XFs.push(val); break; | ||||
| 				case 0x01ae /* SupBook */: | ||||
| @ -301,11 +298,11 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 				case 0x0012 /* Protect */: out["!protect"] = val; break; /* for sheet or book */ | ||||
| 				case 0x0013 /* Password */: if(val !== 0 && opts.WTF) console.error("Password verifier: " + val); break; | ||||
| 				case 0x0085 /* BoundSheet8 */: { | ||||
| 					Directory[opts.biff == 4 ? opts.snames.length : val.pos] = val; | ||||
| 					Directory[val.pos] = val; | ||||
| 					opts.snames.push(val.name); | ||||
| 				} break; | ||||
| 				case 0x000a /* EOF */: { | ||||
| 					if(--file_depth ? !biff4w : biff4w) break; | ||||
| 					if(--file_depth) break; | ||||
| 					if(range.e) { | ||||
| 						if(range.e.r > 0 && range.e.c > 0) { | ||||
| 							range.e.r--; range.e.c--; | ||||
| @ -326,33 +323,31 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 						Workbook.Sheets.push(wsprops); | ||||
| 					} | ||||
| 					if(cur_sheet === "") Preamble = out; else Sheets[cur_sheet] = out; | ||||
| 					out = ({}/*:any*/); if(options.dense) out["!data"] = []; | ||||
| 					out = ((options.dense ? [] : {})/*:any*/); | ||||
| 				} break; | ||||
| 				case 0x0009: case 0x0209: case 0x0409: case 0x0809 /* BOF */: { | ||||
| 					if(opts.biff === 8) opts.biff = { | ||||
| 						0x0009: 2, | ||||
| 						0x0209: 3, | ||||
| 						0x0409: 4 | ||||
| 						/*::[*/0x0009/*::]*/:2, | ||||
| 						/*::[*/0x0209/*::]*/:3, | ||||
| 						/*::[*/0x0409/*::]*/:4 | ||||
| 					}[RecordType] || { | ||||
| 						0x0200: 2, | ||||
| 						0x0300: 3, | ||||
| 						0x0400: 4, | ||||
| 						0x0500: 5, | ||||
| 						0x0600: 8, | ||||
| 						0x0002: 2, | ||||
| 						0x0007: 2 | ||||
| 						/*::[*/0x0200/*::]*/:2, | ||||
| 						/*::[*/0x0300/*::]*/:3, | ||||
| 						/*::[*/0x0400/*::]*/:4, | ||||
| 						/*::[*/0x0500/*::]*/:5, | ||||
| 						/*::[*/0x0600/*::]*/:8, | ||||
| 						/*::[*/0x0002/*::]*/:2, | ||||
| 						/*::[*/0x0007/*::]*/:2 | ||||
| 					}[val.BIFFVer] || 8; | ||||
| 					opts.biffguess = val.BIFFVer == 0; | ||||
| 					if(val.BIFFVer == 0 && val.dt == 0x1000) { opts.biff = 5; seen_codepage = true; set_cp(opts.codepage = 28591); } | ||||
| 					if(opts.biff == 4 && val.dt & 0x100) biff4w = true; | ||||
| 					if(opts.biff == 8 && val.BIFFVer == 0 && val.dt == 16) opts.biff = 2; | ||||
| 					if(file_depth++ && !biff4w) break; | ||||
| 					out = ({}/*:any*/); if(options.dense) out["!data"] = []; | ||||
| 					if(file_depth++) break; | ||||
| 					out = ((options.dense ? [] : {})/*:any*/); | ||||
| 
 | ||||
| 					if(opts.biff < 8 && !seen_codepage) { seen_codepage = true; set_cp(opts.codepage = options.codepage || 1252); } | ||||
| 					if(opts.biff == 4 && biff4w) { | ||||
| 						cur_sheet = (Directory[opts.snames.indexOf(cur_sheet)+1] || {name:""}).name; | ||||
| 					} else if(opts.biff < 5 || val.BIFFVer == 0 && val.dt == 0x1000) { | ||||
| 
 | ||||
| 					if(opts.biff < 5 || val.BIFFVer == 0 && val.dt == 0x1000) { | ||||
| 						if(cur_sheet === "") cur_sheet = "Sheet1"; | ||||
| 						range = {s:{r:0,c:0},e:{r:0,c:0}}; | ||||
| 						/* fake BoundSheet8 */ | ||||
| @ -371,21 +366,21 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 					wsprops = {Hidden:(Directory[s]||{hs:0}).hs, name:cur_sheet }; | ||||
| 				} break; | ||||
| 				case 0x0203 /* Number */: case 0x0003 /* BIFF2NUM */: case 0x0002 /* BIFF2INT */: { | ||||
| 					if(out["!type"] == "chart") if(options.dense ? (out["!data"][val.r]||[])[val.c]: out[encode_col(val.c) + encode_row(val.r)]) ++val.c; | ||||
| 					if(out["!type"] == "chart") if(options.dense ? (out[val.r]||[])[val.c]: out[encode_cell({c:val.c, r:val.r})]) ++val.c; | ||||
| 					temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe]||{}, v:val.val, t:'n'}/*:any*/); | ||||
| 					if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F]; | ||||
| 					if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F]; | ||||
| 					safe_format_xf(temp_val, options, wb.opts.Date1904); | ||||
| 					addcell({c:val.c, r:val.r}, temp_val, options); | ||||
| 				} break; | ||||
| 				case 0x0005: case 0x0205 /* BoolErr */: { | ||||
| 					temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:val.t}/*:any*/); | ||||
| 					if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F]; | ||||
| 					if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F]; | ||||
| 					safe_format_xf(temp_val, options, wb.opts.Date1904); | ||||
| 					addcell({c:val.c, r:val.r}, temp_val, options); | ||||
| 				} break; | ||||
| 				case 0x027e /* RK */: { | ||||
| 					temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.rknum, t:'n'}/*:any*/); | ||||
| 					if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F]; | ||||
| 					if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F]; | ||||
| 					safe_format_xf(temp_val, options, wb.opts.Date1904); | ||||
| 					addcell({c:val.c, r:val.r}, temp_val, options); | ||||
| 				} break; | ||||
| @ -393,7 +388,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 					for(var j = val.c; j <= val.C; ++j) { | ||||
| 						var ixfe = val.rkrec[j-val.c][0]; | ||||
| 						temp_val= ({ixfe:ixfe, XF:XFs[ixfe], v:val.rkrec[j-val.c][1], t:'n'}/*:any*/); | ||||
| 						if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F]; | ||||
| 						if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F]; | ||||
| 						safe_format_xf(temp_val, options, wb.opts.Date1904); | ||||
| 						addcell({c:j, r:val.r}, temp_val, options); | ||||
| 					} | ||||
| @ -408,10 +403,10 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 							var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1]; | ||||
| 							var _fe = encode_cell({r:_fr, c:_fc}); | ||||
| 							if(sharedf[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); | ||||
| 							else temp_val.F = ((options.dense ? (out["!data"][_fr]||[])[_fc]: out[_fe]) || {}).F; | ||||
| 							else temp_val.F = ((options.dense ? (out[_fr]||[])[_fc]: out[_fe]) || {}).F; | ||||
| 						} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); | ||||
| 					} | ||||
| 					if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F]; | ||||
| 					if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F]; | ||||
| 					safe_format_xf(temp_val, options, wb.opts.Date1904); | ||||
| 					addcell(val.cell, temp_val, options); | ||||
| 					last_formula = val; | ||||
| @ -424,7 +419,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 						if(options.cellFormula) { | ||||
| 							temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts); | ||||
| 						} | ||||
| 						if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F]; | ||||
| 						if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F]; | ||||
| 						safe_format_xf(temp_val, options, wb.opts.Date1904); | ||||
| 						addcell(last_formula.cell, temp_val, options); | ||||
| 						last_formula = null; | ||||
| @ -433,7 +428,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 				case 0x0021: case 0x0221 /* Array */: { | ||||
| 					arrayf.push(val); | ||||
| 					var _arraystart = encode_cell(val[0].s); | ||||
| 					cc = options.dense ? (out["!data"][val[0].s.r]||[])[val[0].s.c] : out[_arraystart]; | ||||
| 					cc = options.dense ? (out[val[0].s.r]||[])[val[0].s.c] : out[_arraystart]; | ||||
| 					if(options.cellFormula && cc) { | ||||
| 						if(!last_formula) break; /* technically unreachable */ | ||||
| 						if(!_arraystart || !cc) break; | ||||
| @ -447,7 +442,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 						/* TODO: capture range */ | ||||
| 						if(!last_formula) break; /* technically unreachable */ | ||||
| 						sharedf[encode_cell(last_formula.cell)]= val[0]; | ||||
| 						cc = options.dense ? (out["!data"][last_formula.cell.r]||[])[last_formula.cell.c] : out[encode_cell(last_formula.cell)]; | ||||
| 						cc = options.dense ? (out[last_formula.cell.r]||[])[last_formula.cell.c] : out[encode_cell(last_formula.cell)]; | ||||
| 						(cc||{}).f = ""+stringify_formula(val[0], range, lastcell, supbooks, opts); | ||||
| 					} | ||||
| 				} break; | ||||
| @ -455,13 +450,13 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 					temp_val=make_cell(sst[val.isst].t, val.ixfe, 's'); | ||||
| 					if(sst[val.isst].h) temp_val.h = sst[val.isst].h; | ||||
| 					temp_val.XF = XFs[temp_val.ixfe]; | ||||
| 					if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F]; | ||||
| 					if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F]; | ||||
| 					safe_format_xf(temp_val, options, wb.opts.Date1904); | ||||
| 					addcell({c:val.c, r:val.r}, temp_val, options); | ||||
| 					break; | ||||
| 				case 0x0201 /* Blank */: if(options.sheetStubs) { | ||||
| 					temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], t:'z'}/*:any*/); | ||||
| 					if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F]; | ||||
| 					if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F]; | ||||
| 					safe_format_xf(temp_val, options, wb.opts.Date1904); | ||||
| 					addcell({c:val.c, r:val.r}, temp_val, options); | ||||
| 				} break; | ||||
| @ -469,7 +464,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 					for(var _j = val.c; _j <= val.C; ++_j) { | ||||
| 						var _ixfe = val.ixfe[_j-val.c]; | ||||
| 						temp_val= ({ixfe:_ixfe, XF:XFs[_ixfe], t:'z'}/*:any*/); | ||||
| 						if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F]; | ||||
| 						if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F]; | ||||
| 						safe_format_xf(temp_val, options, wb.opts.Date1904); | ||||
| 						addcell({c:_j, r:val.r}, temp_val, options); | ||||
| 					} | ||||
| @ -478,7 +473,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 				case 0x0204 /* Label */: case 0x0004 /* BIFF2STR */: | ||||
| 					temp_val=make_cell(val.val, val.ixfe, 's'); | ||||
| 					temp_val.XF = XFs[temp_val.ixfe]; | ||||
| 					if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F]; | ||||
| 					if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F]; | ||||
| 					safe_format_xf(temp_val, options, wb.opts.Date1904); | ||||
| 					addcell({c:val.c, r:val.r}, temp_val, options); | ||||
| 					break; | ||||
| @ -490,7 +485,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 					sst = val; | ||||
| 				} break; | ||||
| 				case 0x041e /* Format */: { /* val = [id, fmt] */ | ||||
| 					if(opts.biff >= 3 && opts.biff <= 4) { | ||||
| 					if(opts.biff == 4) { | ||||
| 						BIFF2FmtTable[BIFF2Fmt++] = val[1]; | ||||
| 						for(var b4idx = 0; b4idx < BIFF2Fmt + 163; ++b4idx) if(table_fmt[b4idx] == val[1]) break; | ||||
| 						if(b4idx >= 163) SSF__load(val[1], BIFF2Fmt + 163); | ||||
| @ -512,24 +507,25 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 				case 0x01b8 /* HLink */: { | ||||
| 					for(rngR = val[0].s.r; rngR <= val[0].e.r; ++rngR) | ||||
| 						for(rngC = val[0].s.c; rngC <= val[0].e.c; ++rngC) { | ||||
| 							cc = options.dense ? (out["!data"][rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})]; | ||||
| 							cc = options.dense ? (out[rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})]; | ||||
| 							if(cc) cc.l = val[1]; | ||||
| 						} | ||||
| 				} break; | ||||
| 				case 0x0800 /* HLinkTooltip */: { | ||||
| 					for(rngR = val[0].s.r; rngR <= val[0].e.r; ++rngR) | ||||
| 						for(rngC = val[0].s.c; rngC <= val[0].e.c; ++rngC) { | ||||
| 							cc = options.dense ? (out["!data"][rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})]; | ||||
| 							cc = options.dense ? (out[rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})]; | ||||
| 							if(cc && cc.l) cc.l.Tooltip = val[1]; | ||||
| 							} | ||||
| 				} break; | ||||
| 				case 0x001c /* Note */: { | ||||
| 					/* TODO: comment continuation (row == -1 / 0xFFFF) */ | ||||
| 					cc = options.dense ? (out["!data"][val[0].r]||[])[val[0].c] : out[encode_cell(val[0])]; | ||||
| 					if(opts.biff <= 5 && opts.biff >= 2) break; /* TODO: BIFF5 */ | ||||
| 					cc = options.dense ? (out[val[0].r]||[])[val[0].c] : out[encode_cell(val[0])]; | ||||
| 					var noteobj = objects[val[2]]; | ||||
| 					if(!cc) { | ||||
| 						if(options.dense) { | ||||
| 							if(!out["!data"][val[0].r]) out["!data"][val[0].r] = []; | ||||
| 							cc = out["!data"][val[0].r][val[0].c] = ({t:"z"}/*:any*/); | ||||
| 							if(!out[val[0].r]) out[val[0].r] = []; | ||||
| 							cc = out[val[0].r][val[0].c] = ({t:"z"}/*:any*/); | ||||
| 						} else { | ||||
| 							cc = out[encode_cell(val[0])] = ({t:"z"}/*:any*/); | ||||
| 						} | ||||
| @ -539,12 +535,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 						range.s.c = Math.min(range.s.c, val[0].c); | ||||
| 					} | ||||
| 					if(!cc.c) cc.c = []; | ||||
| 					if(opts.biff <= 5 && opts.biff >= 2) cmnt = {a:"SheetJ5", t:val[1]}; | ||||
| 					else { | ||||
| 						var noteobj = objects[val[2]]; | ||||
| 						cmnt = {a:val[1],t:noteobj.TxO.t}; | ||||
| 						if(val[3] != null && !(val[3] & 0x02)) cc.c.hidden = true; | ||||
| 					} | ||||
| 					cmnt = {a:val[1],t:noteobj.TxO.t}; | ||||
| 					cc.c.push(cmnt); | ||||
| 				} break; | ||||
| 				case 0x087d /* XFExt */: update_xfext(XFs[val.ixfe], val.ext); break; | ||||
| @ -627,14 +618,14 @@ function parse_xls_props(cfb/*:CFBContainer*/, props, o) { | ||||
| 	if(DSI && DSI.size > 0) try { | ||||
| 		var DocSummary = parse_PropertySetStream(DSI, DocSummaryPIDDSI, PSCLSID.DSI); | ||||
| 		for(var d in DocSummary) props[d] = DocSummary[d]; | ||||
| 	} catch(e) {if(o.WTF) console.error(e && e.message || e);} | ||||
| 	} catch(e) {if(o.WTF) throw e;/* empty */} | ||||
| 
 | ||||
| 	/* [MS-OSHARED] 2.3.3.2.1 Summary Information Property Set*/ | ||||
| 	var SI = CFB.find(cfb, '/!SummaryInformation'); | ||||
| 	if(SI && SI.size > 0) try { | ||||
| 		var Summary = parse_PropertySetStream(SI, SummaryPIDSI, PSCLSID.SI); | ||||
| 		for(var s in Summary) if(props[s] == null) props[s] = Summary[s]; | ||||
| 	} catch(e) {if(o.WTF) console.error(e && e.message || e);} | ||||
| 	} catch(e) {if(o.WTF) throw e;/* empty */} | ||||
| 
 | ||||
| 	if(props.HeadingPairs && props.TitlesOfParts) { | ||||
| 		load_props_pairs(props.HeadingPairs, props.TitlesOfParts, props, o); | ||||
|  | ||||
							
								
								
									
										2624
									
								
								bits/77_parsetab.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										2624
									
								
								bits/77_parsetab.js
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -31,6 +31,15 @@ function write_biff_continue(ba/*:BufArray*/, type/*:number*/, payload, length/* | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| function write_BIFF2Cell(out, r/*:number*/, c/*:number*/) { | ||||
| 	if(!out) out = new_buf(7); | ||||
| 	out.write_shift(2, r); | ||||
| 	out.write_shift(2, c); | ||||
| 	out.write_shift(2, 0); | ||||
| 	out.write_shift(1, 0); | ||||
| 	return out; | ||||
| } | ||||
| 
 | ||||
| function write_BIFF2BERR(r/*:number*/, c/*:number*/, val, t/*:?string*/) { | ||||
| 	var out = new_buf(9); | ||||
| 	write_BIFF2Cell(out, r, c); | ||||
| @ -47,371 +56,62 @@ function write_BIFF2LABEL(r/*:number*/, c/*:number*/, val) { | ||||
| 	return out.l < out.length ? out.slice(0, out.l) : out; | ||||
| } | ||||
| 
 | ||||
| function write_comments_biff2(ba/*:BufArray*/, comments/*:Array<[Comment[], number, number]>*/) { | ||||
| 	comments.forEach(function(data) { | ||||
| 		var text = data[0].map(function(cc) { return cc.t; }).join(""); | ||||
| 		// TODO: should '\n' be translated to '\r' to correct for Excel 5.0 bug when exporting to BIFF2/3 ?
 | ||||
| 		if(text.length <= 2048) return write_biff_rec(ba, 0x001C, write_NOTE_BIFF2(text, data[1], data[2])); | ||||
| 		write_biff_rec(ba, 0x001C, write_NOTE_BIFF2(text.slice(0, 2048), data[1], data[2], text.length)); | ||||
| 		for(var i = 2048; i < text.length; i += 2048) | ||||
| 			write_biff_rec(ba, 0x001C, write_NOTE_BIFF2(text.slice(i, Math.min(i+2048, text.length)), -1, -1, Math.min(2048, text.length - i))); | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| /* TODO: BIFF3/4 use different records -- see comments*/ | ||||
| function write_ws_biff2_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, date1904/*:boolean*/) { | ||||
| 	var ifmt = 0; | ||||
| 	if(cell.z != null) { | ||||
| 		ifmt = opts._BIFF2FmtTable.indexOf(cell.z); | ||||
| 		if(ifmt == -1) { opts._BIFF2FmtTable.push(cell.z); ifmt = opts._BIFF2FmtTable.length - 1; } | ||||
| 	} | ||||
| 	var ixfe = 0; | ||||
| 	if(cell.z != null) { | ||||
| 		for(; ixfe < opts.cellXfs.length; ++ixfe) if(opts.cellXfs[ixfe].numFmtId == ifmt) break; | ||||
| 		if(ixfe == opts.cellXfs.length) opts.cellXfs.push({numFmtId: ifmt}); | ||||
| 	} | ||||
| function write_ws_biff2_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*//*::, opts*/) { | ||||
| 	if(cell.v != null) switch(cell.t) { | ||||
| 		case 'd': case 'n': | ||||
| 			var v = cell.t == 'd' ? datenum(parseDate(cell.v, date1904), date1904) : cell.v; | ||||
| 			if(opts.biff == 2 && (v == (v|0)) && (v >= 0) && (v < 65536)) | ||||
| 				// 0x027E (RK) in BIFF3/4
 | ||||
| 				write_biff_rec(ba, 0x0002, write_BIFF2INT(R, C, v, ixfe, ifmt)); | ||||
| 			else if(isNaN(v)) | ||||
| 				// 0x0205 in BIFF3/4
 | ||||
| 				write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, 0x24, "e")); // #NUM!
 | ||||
| 			else if(!isFinite(v)) | ||||
| 				// 0x0205 in BIFF3/4
 | ||||
| 				write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, 0x07, "e")); // #DIV/0!
 | ||||
| 			var v = cell.t == 'd' ? datenum(parseDate(cell.v)) : cell.v; | ||||
| 			if((v == (v|0)) && (v >= 0) && (v < 65536)) | ||||
| 				write_biff_rec(ba, 0x0002, write_BIFF2INT(R, C, v)); | ||||
| 			else | ||||
| 				// 0x0203 in BIFF3/4
 | ||||
| 				write_biff_rec(ba, 0x0003, write_BIFF2NUM(R,C, v, ixfe, ifmt)); | ||||
| 				write_biff_rec(ba, 0x0003, write_BIFF2NUM(R,C, v)); | ||||
| 			return; | ||||
| 		case 'b': case 'e': | ||||
| 			// 0x0205 in BIFF3/4
 | ||||
| 			write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); return; | ||||
| 		case 'b': case 'e': write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); return; | ||||
| 		/* TODO: codepage, sst */ | ||||
| 		case 's': case 'str': | ||||
| 			// 0x0204 in BIFF3/4
 | ||||
| 			write_biff_rec(ba, 0x0004, write_BIFF2LABEL(R, C, cell.v == null ? "" : String(cell.v).slice(0,255))); | ||||
| 			write_biff_rec(ba, 0x0004, write_BIFF2LABEL(R, C, (cell.v||"").slice(0,255))); | ||||
| 			return; | ||||
| 	} | ||||
| 	// 0x0201 in BIFF3/4
 | ||||
| 	write_biff_rec(ba, 0x0001, write_BIFF2Cell(null, R, C)); | ||||
| } | ||||
| 
 | ||||
| function write_ws_biff2(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbook*/) { | ||||
| 	var dense = ws["!data"] != null; | ||||
| 	var range = safe_decode_range(ws['!ref'] || "A1"), rr = "", cols/*:Array<string>*/ = []; | ||||
| function write_ws_biff2(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts/*::, wb:Workbook*/) { | ||||
| 	var dense = Array.isArray(ws); | ||||
| 	var range = safe_decode_range(ws['!ref'] || "A1"), ref/*:string*/, rr = "", cols/*:Array<string>*/ = []; | ||||
| 	if(range.e.c > 0xFF || range.e.r > 0x3FFF) { | ||||
| 		if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV16384"); | ||||
| 		range.e.c = Math.min(range.e.c, 0xFF); | ||||
| 		range.e.r = Math.min(range.e.r, 0x3FFF); | ||||
| 		range.e.r = Math.min(range.e.c, 0x3FFF); | ||||
| 		ref = encode_range(range); | ||||
| 	} | ||||
| 	var date1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904; | ||||
| 	var row = [], comments = []; | ||||
| 	/* TODO: 0x0000 / 0x0200 dimensions? */ | ||||
| 	for(var C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C); | ||||
| 	for(var R = range.s.r; R <= range.e.r; ++R) { | ||||
| 		if(dense) row = ws["!data"][R] || []; | ||||
| 		rr = encode_row(R); | ||||
| 		for(C = range.s.c; C <= range.e.c; ++C) { | ||||
| 			var cell = dense ? row[C] : ws[cols[C] + rr]; | ||||
| 		for(var C = range.s.c; C <= range.e.c; ++C) { | ||||
| 			if(R === range.s.r) cols[C] = encode_col(C); | ||||
| 			ref = cols[C] + rr; | ||||
| 			var cell = dense ? (ws[R]||[])[C] : ws[ref]; | ||||
| 			if(!cell) continue; | ||||
| 			/* write cell */ | ||||
| 			write_ws_biff2_cell(ba, cell, R, C, opts, date1904); | ||||
| 			if(cell.c) comments.push([cell.c, R, C]); | ||||
| 			write_ws_biff2_cell(ba, cell, R, C, opts); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* ... 0x12 0x19 0x13 (Password) */ | ||||
| 	write_comments_biff2(ba, comments); | ||||
| 	/* 0x3d (Window1) ... */ | ||||
| } | ||||
| 
 | ||||
| /* Based on test files */ | ||||
| function write_biff2_buf(wb/*:Workbook*/, opts/*:WriteOpts*/) { | ||||
| 	var o = opts || {}; | ||||
| 
 | ||||
| 	if(DENSE != null && o.dense == null) o.dense = DENSE; | ||||
| 	var ba = buf_array(); | ||||
| 	var idx = 0; | ||||
| 	for(var i=0;i<wb.SheetNames.length;++i) if(wb.SheetNames[i] == o.sheet) idx=i; | ||||
| 	if(idx == 0 && !!o.sheet && wb.SheetNames[0] != o.sheet) throw new Error("Sheet not found: " + o.sheet); | ||||
| 	write_biff_rec(ba, (o.biff == 4 ? 0x0409 : (o.biff == 3 ? 0x0209 : 0x0009)), write_BOF(wb, 0x10, o)); | ||||
| 	if(((wb.Workbook||{}).WBProps||{}).date1904) write_biff_rec(ba, 0x0022, writebool(true)); | ||||
| 	o.cellXfs = [{numFmtId: 0}]; | ||||
| 	o._BIFF2FmtTable/*:Array<string>*/ = ["General"]; o._Fonts = []; | ||||
| 	var body = buf_array(); | ||||
| 	write_ws_biff2(body, wb.Sheets[wb.SheetNames[idx]], idx, o, wb); | ||||
| 
 | ||||
| 	o._BIFF2FmtTable.forEach(function(f) { | ||||
| 		if(o.biff <= 3) write_biff_rec(ba, 0x001E, write_BIFF2Format(f)); | ||||
| 		else write_biff_rec(ba, 0x041E, write_BIFF4Format(f)); | ||||
| 	}); | ||||
| 	o.cellXfs.forEach(function(xf) { | ||||
| 		switch(o.biff) { | ||||
| 			case 2: write_biff_rec(ba, 0x0043, write_BIFF2XF(xf)); break; | ||||
| 			case 3: write_biff_rec(ba, 0x0243, write_BIFF3XF(xf)); break; | ||||
| 			case 4: write_biff_rec(ba, 0x0443, write_BIFF4XF(xf)); break; | ||||
| 		} | ||||
| 	}); | ||||
| 	delete o._BIFF2FmtTable; delete o.cellXfs; delete o._Fonts; | ||||
| 
 | ||||
| 	ba.push(body.end()); | ||||
| 	/* ... */ | ||||
| 	write_ws_biff2(ba, wb.Sheets[wb.SheetNames[idx]], idx, o, wb); | ||||
| 	/* ... */ | ||||
| 	write_biff_rec(ba, 0x000A); | ||||
| 	return ba.end(); | ||||
| } | ||||
| 
 | ||||
| var b8oid = 1, b8ocnts/*:Array<[number, number, number]>*/ = []; | ||||
| function write_MsoDrawingGroup() { | ||||
| 	var buf = new_buf(82 + 8 * b8ocnts.length); | ||||
| 	/* [MS-ODRAW] 2.2.12 OfficeArtDggContainer */ | ||||
| 	buf.write_shift(2, 0x0F); | ||||
| 	buf.write_shift(2, 0xF000); | ||||
| 	buf.write_shift(4, 74 + 8 * b8ocnts.length); | ||||
| 	/* 2.2.48 OfficeArtFDGGBlock */ | ||||
| 	{ | ||||
| 		buf.write_shift(2, 0); | ||||
| 		buf.write_shift(2, 0xF006); | ||||
| 		buf.write_shift(4, 16 + 8 * b8ocnts.length); | ||||
| 		/* 2.2.47 OfficeArtFDGG */ | ||||
| 		{ | ||||
| 			buf.write_shift(4, b8oid); | ||||
| 			buf.write_shift(4, b8ocnts.length+1); | ||||
| 			var acc = 0; for(var i = 0; i < b8ocnts.length; ++i) acc += (b8ocnts[i] && b8ocnts[i][1] || 0); buf.write_shift(4, acc); | ||||
| 			buf.write_shift(4, b8ocnts.length); | ||||
| 		} | ||||
| 		/* 2.2.46 OfficeArtIDCL + */ | ||||
| 		b8ocnts.forEach(function(b8) { | ||||
| 			buf.write_shift(4, b8[0]); | ||||
| 			buf.write_shift(4, b8[2]); | ||||
| 		}); | ||||
| 	} | ||||
| 	/* 2.2.9 OfficeArtFOPT */ | ||||
| 	{ | ||||
| 		buf.write_shift(2, 0x33); // 0x03 | (3 << 4)
 | ||||
| 		buf.write_shift(2, 0xF00B); | ||||
| 		buf.write_shift(4, 0x12); // 3 * 6
 | ||||
| 		/* 2.3.21.15 Text Boolean Properties */ | ||||
| 		buf.write_shift(2, 0xBF); buf.write_shift(4, 0x00080008); | ||||
| 		/* 2.3.7.2 fillColor */ | ||||
| 		buf.write_shift(2, 0x0181); buf.write_shift(4, 0x08000041); | ||||
| 		/* 2.3.8.1 lineColor */ | ||||
| 		buf.write_shift(2, 0x01C0); buf.write_shift(4, 0x08000040); | ||||
| 	} | ||||
| 	/* 2.2.45 OfficeArtSplitMenuColorContainer */ | ||||
| 	{ | ||||
| 		buf.write_shift(2, 0x40); | ||||
| 		buf.write_shift(2, 0xF11E); | ||||
| 		buf.write_shift(4, 16); | ||||
| 		buf.write_shift(4, 0x0800000D); | ||||
| 		buf.write_shift(4, 0x0800000C); | ||||
| 		buf.write_shift(4, 0x08000017); | ||||
| 		buf.write_shift(4, 0x100000F7); | ||||
| 	} | ||||
| 	return buf; | ||||
| } | ||||
| function write_comments_biff8(ba/*:BufArray*/, comments/*:Array<[Comment[], number, number]>*/) { | ||||
| 	var notes/*:Array<RawData>*/ = [], sz = 0, pl = buf_array(), baseid = b8oid; | ||||
| 	var _oasc; | ||||
| 	comments.forEach(function(c, ci) { | ||||
| 		var author = ""; | ||||
| 		var text = c[0].map(function(t) { if(t.a && !author) author = t.a; return t.t; }).join(""); | ||||
| 		++b8oid; | ||||
| 
 | ||||
| 		/* 2.2.14 OfficeArtSpContainer */ | ||||
| 		{ | ||||
| 			var oasc = new_buf(0x96); | ||||
| 			oasc.write_shift(2, 0x0F); | ||||
| 			oasc.write_shift(2, 0xF004); | ||||
| 			oasc.write_shift(4, 0x96); | ||||
| 			/* 2.2.40 OfficeArtFSP */ | ||||
| 			{ | ||||
| 				oasc.write_shift(2, 0xca2); // 0x02 | (0xca << 4)
 | ||||
| 				oasc.write_shift(2, 0xF00A); | ||||
| 				oasc.write_shift(4, 8); | ||||
| 				oasc.write_shift(4, b8oid); | ||||
| 				oasc.write_shift(4, 0xA00); | ||||
| 			} | ||||
| 			/* 2.2.9 OfficeArtFOPT */ | ||||
| 			{ | ||||
| 				oasc.write_shift(2, 0xE3); // 0x03 | (14 << 4)
 | ||||
| 				oasc.write_shift(2, 0xF00B); | ||||
| 				oasc.write_shift(4, 0x54); // 14 * 6
 | ||||
| 				/* 2.3.21.1 ITxid */ | ||||
| 				oasc.write_shift(2, 0x80); oasc.write_shift(4, 0); | ||||
| 				/* 2.3.21.12 txdir */ | ||||
| 				oasc.write_shift(2, 0x8B); oasc.write_shift(4, 0x02); | ||||
| 				/* 2.3.21.15 Text Boolean Properties */ | ||||
| 				oasc.write_shift(2, 0xBF); oasc.write_shift(4, 0x00080008); | ||||
| 				/* 2.3.6.30 cxk */ | ||||
| 				oasc.write_shift(2, 0x0158); oasc.l += 4; | ||||
| 				/* 2.3.7.2 fillColor */ | ||||
| 				oasc.write_shift(2, 0x0181); oasc.write_shift(4, 0x08000050); | ||||
| 				/* 2.3.7.4 fillBackColor */ | ||||
| 				oasc.write_shift(2, 0x0183); oasc.write_shift(4, 0x08000050); | ||||
| 				/* 2.3.7.6 fillCrMod */ | ||||
| 				oasc.write_shift(2, 0x0185); oasc.write_shift(4, 0x100000F4); | ||||
| 				/* 2.3.7.43 Fill Style Boolean Properties */ | ||||
| 				oasc.write_shift(2, 0x01BF); oasc.write_shift(4, 0x00100010); | ||||
| 				/* 2.3.8.1 lineColor */ | ||||
| 				oasc.write_shift(2, 0x01C0); oasc.write_shift(4, 0x08000051); | ||||
| 				/* 2.3.8.4 lineCrMod */ | ||||
| 				oasc.write_shift(2, 0x01C3); oasc.write_shift(4, 0x100000F4); | ||||
| 				/* 2.3.13.2 shadowColor */ | ||||
| 				oasc.write_shift(2, 0x0201); oasc.write_shift(4, 0x08000051); | ||||
| 				/* 2.3.13.4 shadowCrMod */ | ||||
| 				oasc.write_shift(2, 0x0203); oasc.write_shift(4, 0x100000F4); | ||||
| 				/* 2.3.13.23 Shadow Style Boolean Properties */ | ||||
| 				oasc.write_shift(2, 0x023F); oasc.write_shift(4, 0x00030001); | ||||
| 				/* 2.3.4.44 Group Shape Boolean Properties */ | ||||
| 				oasc.write_shift(2, 0x03BF); oasc.write_shift(4, 0x00020000 | (c[0].hidden ? 2 : 0)); | ||||
| 			} | ||||
| 			/* [MS-XLS] 2.5.193 OfficeArtClientAnchorSheet */ | ||||
| 			{ | ||||
| 				oasc.l += 2; | ||||
| 				oasc.write_shift(2, 0xF010); | ||||
| 				oasc.write_shift(4, 0x12); | ||||
| 				oasc.write_shift(2, 0x3); // do not move or size with cells
 | ||||
| 				oasc.write_shift(2, c[2] + 2); oasc.l += 2; | ||||
| 				oasc.write_shift(2, c[1] + 1); oasc.l += 2; | ||||
| 				oasc.write_shift(2, c[2] + 4); oasc.l += 2; | ||||
| 				oasc.write_shift(2, c[1] + 5); oasc.l += 2; | ||||
| 			} | ||||
| 			/* [MS-XLS] 2.5.194 OfficeArtClientData */ | ||||
| 			{ | ||||
| 				oasc.l += 2; | ||||
| 				oasc.write_shift(2, 0xF011); | ||||
| 				oasc.l += 4; | ||||
| 			} | ||||
| 			oasc.l = 0x96; | ||||
| 			if(ci == 0) /* write_biff_rec(pl, 0x003C, oasc); */ _oasc = oasc; | ||||
| 			else write_biff_rec(pl, 0x00EC, oasc); | ||||
| 		} | ||||
| 		sz += 0x96; | ||||
| 
 | ||||
| 		/* [MS-XLS] 2.4.181 Obj */ | ||||
| 		{ | ||||
| 			var obj = new_buf(52); // 22 + 26 + 4
 | ||||
| 			/* [MS-XLS] 2.5.143 FtCmo */ | ||||
| 			obj.write_shift(2, 0x15); | ||||
| 			obj.write_shift(2, 0x12); | ||||
| 			obj.write_shift(2, 0x19); | ||||
| 			obj.write_shift(2, b8oid); | ||||
| 			obj.write_shift(2, 0); | ||||
| 			obj.l = 22; | ||||
| 			/* [MS-XLS] 2.5.149 FtNts */ | ||||
| 			obj.write_shift(2, 0x0D); | ||||
| 			obj.write_shift(2, 0x16); | ||||
| 			obj.write_shift(4, 0x62726272); | ||||
| 			obj.write_shift(4, 0x95374305); | ||||
| 			obj.write_shift(4, 0x80301328); | ||||
| 			obj.write_shift(4, 0x69696904 + b8oid*256); | ||||
| 			obj.write_shift(2,0); | ||||
| 			obj.write_shift(4,0); | ||||
| 			// reserved
 | ||||
| 			obj.l += 4; | ||||
| 			write_biff_rec(pl, 0x005D, obj); | ||||
| 		} | ||||
| 
 | ||||
| 		/* [MS-XLS] 2.5.195 OfficeArtClientTextbox */ | ||||
| 		{ | ||||
| 			var oact = new_buf(8); | ||||
| 			oact.l += 2; | ||||
| 			oact.write_shift(2, 0xF00D); | ||||
| 			oact.l += 4; | ||||
| 			write_biff_rec(pl, 0x00EC, oact); | ||||
| 		} | ||||
| 		sz += 8; | ||||
| 
 | ||||
| 		/* [MS-XLS] 2.4.329 TxO */ | ||||
| 		{ | ||||
| 			var txo = new_buf(18); | ||||
| 			txo.write_shift(2, 0x12); | ||||
| 			txo.l += 8; | ||||
| 			txo.write_shift(2, text.length); | ||||
| 			txo.write_shift(2, 0x10); | ||||
| 			txo.l += 4; | ||||
| 			write_biff_rec(pl, 0x01b6, txo); | ||||
| 			/* text continue record TODO: switch to wide strings */ | ||||
| 			{ | ||||
| 				var cont = new_buf(1 + text.length); | ||||
| 				cont.write_shift(1, 0); | ||||
| 				cont.write_shift(text.length, text, "sbcs"); | ||||
| 				write_biff_rec(pl, 0x003C, cont); | ||||
| 			} | ||||
| 			/* formatting continue records */ | ||||
| 			{ | ||||
| 				var conf = new_buf(0x10); | ||||
| 				conf.l += 8; | ||||
| 				conf.write_shift(2, text.length); | ||||
| 				conf.l += 6; | ||||
| 				write_biff_rec(pl, 0x003C, conf); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		/* 2.4.179 Note */ | ||||
| 		{ | ||||
| 			var notesh = new_buf(12 + author.length); | ||||
| 			notesh.write_shift(2, c[1]); | ||||
| 			notesh.write_shift(2, c[2]); | ||||
| 			notesh.write_shift(2, 0 | (c[0].hidden ? 0 : 2)); | ||||
| 			notesh.write_shift(2, b8oid); | ||||
| 			notesh.write_shift(2, author.length); | ||||
| 			notesh.write_shift(1, 0); | ||||
| 			notesh.write_shift(author.length, author, "sbcs"); | ||||
| 			notesh.l ++; | ||||
| 			notes.push(notesh); | ||||
| 		} | ||||
| 	}); | ||||
| 	/* [MS-ODRAW] 2.2.13 OfficeArtDgContainer */ | ||||
| 	{ | ||||
| 		var hdr = new_buf(80); | ||||
| 		hdr.write_shift(2, 0x0F); | ||||
| 		hdr.write_shift(2, 0xF002); | ||||
| 		hdr.write_shift(4, sz + hdr.length - 8); | ||||
| 		/* [MS-ODRAW] 2.2.49 OfficeArtFDG */ | ||||
| 		{ | ||||
| 			hdr.write_shift(2, 0x10); | ||||
| 			hdr.write_shift(2, 0xF008); | ||||
| 			hdr.write_shift(4, 0x08); | ||||
| 			hdr.write_shift(4, comments.length + 1); | ||||
| 			hdr.write_shift(4, b8oid); | ||||
| 		} | ||||
| 		/* [MS-ODRAW] 2.2.16 OfficeArtSpgrContainer */ | ||||
| 		{ | ||||
| 			hdr.write_shift(2, 0x0f); | ||||
| 			hdr.write_shift(2, 0xF003); | ||||
| 			hdr.write_shift(4, sz + 0x30); | ||||
| 			/* [MS-ODRAW] 2.2.14 OfficeArtSpContainer */ | ||||
| 			{ | ||||
| 				hdr.write_shift(2, 0x0f); | ||||
| 				hdr.write_shift(2, 0xF004); | ||||
| 				hdr.write_shift(4, 0x28); | ||||
| 				/* [MS-ODRAW] 2.2.38 OfficeArtFSPGR */ | ||||
| 				{ | ||||
| 					hdr.write_shift(2, 0x01); | ||||
| 					hdr.write_shift(2, 0xF009); | ||||
| 					hdr.write_shift(4, 0x10); | ||||
| 					hdr.l += 16; | ||||
| 				} | ||||
| 				/* [MS-ODRAW] 2.2.40 OfficeArtFSP */ | ||||
| 				{ | ||||
| 					hdr.write_shift(2, 0x02); | ||||
| 					hdr.write_shift(2, 0xF00A); | ||||
| 					hdr.write_shift(4, 0x08); | ||||
| 					hdr.write_shift(4, baseid); | ||||
| 					hdr.write_shift(4, 0x05); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		write_biff_rec(ba, 0x00EC, /* hdr */ _oasc ? bconcat([hdr, _oasc]) : hdr); | ||||
| 	} | ||||
| 	ba.push(pl.end()); | ||||
| 	notes.forEach(function(n) { write_biff_rec(ba, 0x001C, n); }); | ||||
| 	b8ocnts.push([baseid, comments.length + 1, b8oid]); | ||||
| 	++b8oid; | ||||
| } | ||||
| 
 | ||||
| function write_FONTS_biff8(ba, data, opts) { | ||||
| 	write_biff_rec(ba, 0x0031 /* Font */, write_Font({ | ||||
| 		sz:12, | ||||
| @ -473,7 +173,7 @@ function write_ws_cols_biff8(ba, cols) { | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| function write_ws_biff8_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, date1904/*:boolean*/) { | ||||
| function write_ws_biff8_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts) { | ||||
| 	var os = 16 + get_cell_style(opts.cellXfs, cell, opts); | ||||
| 	if(cell.v == null && !cell.bf) { | ||||
| 		write_biff_rec(ba, 0x0201 /* Blank */, write_XLSCell(R, C, os)); | ||||
| @ -482,11 +182,9 @@ function write_ws_biff8_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:n | ||||
| 	if(cell.bf) write_biff_rec(ba, 0x0006 /* Formula */, write_Formula(cell, R, C, opts, os)); | ||||
| 	else switch(cell.t) { | ||||
| 		case 'd': case 'n': | ||||
| 			var v = cell.t == 'd' ? datenum(parseDate(cell.v, date1904), date1904) : cell.v; | ||||
| 			if(isNaN(v)) write_biff_rec(ba, 0x0205 /* BoolErr */, write_BoolErr(R, C, 0x24, os, opts, "e")); // #NUM!
 | ||||
| 			else if(!isFinite(v)) write_biff_rec(ba, 0x0205 /* BoolErr */, write_BoolErr(R, C, 0x07, os, opts, "e")); // #DIV/0!
 | ||||
| 			var v = cell.t == 'd' ? datenum(parseDate(cell.v)) : cell.v; | ||||
| 			/* TODO: emit RK as appropriate */ | ||||
| 			else write_biff_rec(ba, 0x0203 /* Number */, write_Number(R, C, v, os, opts)); | ||||
| 			write_biff_rec(ba, 0x0203 /* Number */, write_Number(R, C, v, os, opts)); | ||||
| 			break; | ||||
| 		case 'b': case 'e': | ||||
| 			write_biff_rec(ba, 0x0205 /* BoolErr */, write_BoolErr(R, C, cell.v, os, opts, cell.t)); | ||||
| @ -494,9 +192,9 @@ function write_ws_biff8_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:n | ||||
| 		/* TODO: codepage, sst */ | ||||
| 		case 's': case 'str': | ||||
| 			if(opts.bookSST) { | ||||
| 				var isst = get_sst_id(opts.Strings, cell.v == null ? "" : String(cell.v), opts.revStrings); | ||||
| 				var isst = get_sst_id(opts.Strings, cell.v, opts.revStrings); | ||||
| 				write_biff_rec(ba, 0x00fd /* LabelSst */, write_LabelSst(R, C, isst, os, opts)); | ||||
| 			} else write_biff_rec(ba, 0x0204 /* Label */, write_Label(R, C, (cell.v == null ? "" : String(cell.v)).slice(0,255), os, opts)); | ||||
| 			} else write_biff_rec(ba, 0x0204 /* Label */, write_Label(R, C, (cell.v||"").slice(0,255), os, opts)); | ||||
| 			break; | ||||
| 		default: | ||||
| 			write_biff_rec(ba, 0x0201 /* Blank */, write_XLSCell(R, C, os)); | ||||
| @ -509,15 +207,15 @@ function write_ws_biff8(idx/*:number*/, opts, wb/*:Workbook*/) { | ||||
| 	var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {}; | ||||
| 	var _WB/*:WBWBProps*/ = ((wb||{}).Workbook||{}/*:any*/); | ||||
| 	var _sheet/*:WBWSProp*/ = ((_WB.Sheets||[])[idx]||{}/*:any*/); | ||||
| 	var dense = ws["!data"] != null; | ||||
| 	var dense = Array.isArray(ws); | ||||
| 	var b8 = opts.biff == 8; | ||||
| 	var ref/*:string*/, rr = "", cols/*:Array<string>*/ = []; | ||||
| 	var range = safe_decode_range(ws['!ref'] || "A1"); | ||||
| 	var MAX_ROWS = b8 ? 65536 : 16384; | ||||
| 	if(range.e.c > 0xFF || range.e.r >= MAX_ROWS) { | ||||
| 		if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV" + MAX_ROWS); | ||||
| 		if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV16384"); | ||||
| 		range.e.c = Math.min(range.e.c, 0xFF); | ||||
| 		range.e.r = Math.min(range.e.r, MAX_ROWS-1); | ||||
| 		range.e.r = Math.min(range.e.c, MAX_ROWS-1); | ||||
| 	} | ||||
| 
 | ||||
| 	write_biff_rec(ba, 0x0809, write_BOF(wb, 0x10, opts)); | ||||
| @ -543,26 +241,24 @@ function write_ws_biff8(idx/*:number*/, opts, wb/*:Workbook*/) { | ||||
| 	write_biff_rec(ba, 0x0200 /* Dimensions */, write_Dimensions(range, opts)); | ||||
| 	/* ... */ | ||||
| 
 | ||||
| 	var date1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904; | ||||
| 	if(b8) ws['!links'] = []; | ||||
| 	for(var C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C); | ||||
| 	var comments = []; | ||||
| 	var row = []; | ||||
| 	for(var R = range.s.r; R <= range.e.r; ++R) { | ||||
| 		if(dense) row = ws["!data"][R] || []; | ||||
| 		rr = encode_row(R); | ||||
| 		for(C = range.s.c; C <= range.e.c; ++C) { | ||||
| 			var cell = dense ? row[C] : ws[cols[C] + rr]; | ||||
| 		for(var C = range.s.c; C <= range.e.c; ++C) { | ||||
| 			if(R === range.s.r) cols[C] = encode_col(C); | ||||
| 			ref = cols[C] + rr; | ||||
| 			var cell = dense ? (ws[R]||[])[C] : ws[ref]; | ||||
| 			if(!cell) continue; | ||||
| 			/* write cell */ | ||||
| 			write_ws_biff8_cell(ba, cell, R, C, opts, date1904); | ||||
| 			if(b8 && cell.l) ws['!links'].push([cols[C] + rr, cell.l]); | ||||
| 			if(cell.c) comments.push([cell.c, R, C]); | ||||
| 			write_ws_biff8_cell(ba, cell, R, C, opts); | ||||
| 			if(b8 && cell.l) ws['!links'].push([ref, cell.l]); | ||||
| 			if(b8 && cell.c) comments.push([ref, cell.c]); | ||||
| 		} | ||||
| 	} | ||||
| 	var cname/*:string*/ = _sheet.CodeName || _sheet.name || s; | ||||
| 	/* ... */ | ||||
| 	if(b8) write_comments_biff8(ba, comments); else write_comments_biff2(ba, comments); | ||||
| 	// if(b8) comments.forEach(function(comment) { write_biff_rec(ba, 0x001c /* Note */, write_NoteSh(comment)); });
 | ||||
| 	/* ... */ | ||||
| 	if(b8) write_biff_rec(ba, 0x023e /* Window2 */, write_Window2((_WB.Views||[])[0])); | ||||
| 	/* ... */ | ||||
| @ -632,10 +328,8 @@ function write_biff8_global(wb/*:Workbook*/, bufs, opts/*:WriteOpts*/) { | ||||
| 	var C = buf_array(); | ||||
| 	/* METADATA [MTRSettings] [ForceFullCalculation] */ | ||||
| 	if(b8) write_biff_rec(C, 0x008C /* Country */, write_Country()); | ||||
| 	/* *SUPBOOK *LBL *RTD [RecalcId] *HFPicture */ | ||||
| 	/* *SUPBOOK *LBL *RTD [RecalcId] *HFPicture *MSODRAWINGGROUP */ | ||||
| 
 | ||||
| 	/* BIFF8: MsoDrawingGroup [*Continue] */ | ||||
| 	if(b8 && b8ocnts.length) write_biff_rec(C, 0x00EB /* MsoDrawingGroup */, write_MsoDrawingGroup()); | ||||
| 	/* BIFF8: [SST *Continue] ExtSST */ | ||||
| 	if(b8 && opts.Strings) write_biff_continue(C, 0x00FC /* SST */, write_SST(opts.Strings, opts)); | ||||
| 
 | ||||
| @ -678,7 +372,6 @@ function write_biff8_buf(wb/*:Workbook*/, opts/*:WriteOpts*/) { | ||||
| 		o.ssf = wb.SSF; | ||||
| 	} | ||||
| 
 | ||||
| 	b8oid = 1; b8ocnts = []; | ||||
| 	o.Strings = /*::((*/[]/*:: :any):SST)*/; o.Strings.Count = 0; o.Strings.Unique = 0; | ||||
| 	fix_write_opts(o); | ||||
| 
 | ||||
| @ -700,9 +393,6 @@ function write_biff_buf(wb/*:Workbook*/, opts/*:WriteOpts*/) { | ||||
| 		if(range.e.c > 255) { // note: 255 is IV
 | ||||
| 			if(typeof console != "undefined" && console.error) console.error("Worksheet '" + wb.SheetNames[i] + "' extends beyond column IV (255).  Data may be lost."); | ||||
| 		} | ||||
| 		if(range.e.r > 65535) { | ||||
| 			if(typeof console != "undefined" && console.error) console.error("Worksheet '" + wb.SheetNames[i] + "' extends beyond row 65536.  Data may be lost."); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	var o = opts || {}; | ||||
|  | ||||
| @ -1,14 +1,14 @@ | ||||
| /* note: browser DOM element cannot see mso- style attrs, must parse */ | ||||
| function html_to_sheet(str/*:string*/, _opts)/*:Workbook*/ { | ||||
| 	var opts = _opts || {}; | ||||
| 	var dense = (opts.dense != null) ? opts.dense : DENSE; | ||||
| 	var ws/*:Worksheet*/ = ({}/*:any*/); if(dense) ws["!data"] = []; | ||||
| 	str = str_remove_ng(str, "<!--", "-->"); | ||||
| 	if(DENSE != null && opts.dense == null) opts.dense = DENSE; | ||||
| 	var ws/*:Worksheet*/ = opts.dense ? ([]/*:any*/) : ({}/*:any*/); | ||||
| 	str = str.replace(/<!--.*?-->/g, ""); | ||||
| 	var mtch/*:any*/ = str.match(/<table/i); | ||||
| 	if(!mtch) throw new Error("Invalid HTML: could not find <table>"); | ||||
| 	var mtch2/*:any*/ = str.match(/<\/table/i); | ||||
| 	var i/*:number*/ = mtch.index, j/*:number*/ = mtch2 && mtch2.index || str.length; | ||||
| 	var rows = split_regex(str.slice(i, j), /(:?<tr[^<>]*>)/i, "<tr>"); | ||||
| 	var rows = split_regex(str.slice(i, j), /(:?<tr[^>]*>)/i, "<tr>"); | ||||
| 	var R = -1, C = 0, RS = 0, CS = 0; | ||||
| 	var range/*:Range*/ = {s:{r:10000000, c:10000000},e:{r:0,c:0}}; | ||||
| 	var merges/*:Array<Range>*/ = []; | ||||
| @ -45,14 +45,10 @@ function html_to_sheet(str/*:string*/, _opts)/*:Workbook*/ { | ||||
| 			else if(!isNaN(fuzzynum(m))) o = {t:'n', v:fuzzynum(m)}; | ||||
| 			else if(!isNaN(fuzzydate(m).getDate())) { | ||||
| 				o = ({t:'d', v:parseDate(m)}/*:any*/); | ||||
| 				if(opts.UTC === false) o.v = utc_to_local(o.v); | ||||
| 				if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)}/*:any*/); | ||||
| 				o.z = opts.dateNF || table_fmt[14]; | ||||
| 			} else if(m.charCodeAt(0) == 35 /* # */ && RBErr[m] != null) { | ||||
| 				o.t = 'e'; o.w = m; o.v = RBErr[m]; | ||||
| 			} | ||||
| 			if(o.cellText !== false) o.w = m; | ||||
| 			if(dense) { if(!ws["!data"][R]) ws["!data"][R] = []; ws["!data"][R][C] = o; } | ||||
| 			if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = o; } | ||||
| 			else ws[encode_cell({r:R, c:C})] = o; | ||||
| 			C += CS; | ||||
| 		} | ||||
| @ -65,7 +61,6 @@ function make_html_row(ws/*:Worksheet*/, r/*:Range*/, R/*:number*/, o/*:Sheet2HT | ||||
| 	var M/*:Array<Range>*/ = (ws['!merges'] ||[]); | ||||
| 	var oo/*:Array<string>*/ = []; | ||||
| 	var sp = ({}/*:any*/); | ||||
| 	var dense = ws["!data"] != null; | ||||
| 	for(var C = r.s.c; C <= r.e.c; ++C) { | ||||
| 		var RS = 0, CS = 0; | ||||
| 		for(var j = 0; j < M.length; ++j) { | ||||
| @ -75,12 +70,8 @@ function make_html_row(ws/*:Worksheet*/, r/*:Range*/, R/*:number*/, o/*:Sheet2HT | ||||
| 			RS = M[j].e.r - M[j].s.r + 1; CS = M[j].e.c - M[j].s.c + 1; break; | ||||
| 		} | ||||
| 		if(RS < 0) continue; | ||||
| 		var coord = encode_col(C) + encode_row(R); | ||||
| 		var cell = dense ? (ws["!data"][R]||[])[C] : ws[coord]; | ||||
| 		if(cell && cell.t == 'n' && cell.v != null && !isFinite(cell.v)) { | ||||
| 			if(isNaN(cell.v)) cell = ({t:'e', v:0x24, w:BErr[0x24]}); | ||||
| 			else cell = ({t:'e', v:0x07, w:BErr[0x07]}); | ||||
| 		} | ||||
| 		var coord = encode_cell({r:R,c:C}); | ||||
| 		var cell = o.dense ? (ws[R]||[])[C] : ws[coord]; | ||||
| 		/* TODO: html entities */ | ||||
| 		var w = (cell && cell.v != null) && (cell.h || escapehtml(cell.w || (format_cell(cell), cell.w) || "")) || ""; | ||||
| 		sp = ({}/*:any*/); | ||||
| @ -89,11 +80,9 @@ function make_html_row(ws/*:Worksheet*/, r/*:Range*/, R/*:number*/, o/*:Sheet2HT | ||||
| 		if(o.editable) w = '<span contenteditable="true">' + w + '</span>'; | ||||
| 		else if(cell) { | ||||
| 			sp["data-t"] = cell && cell.t || 'z'; | ||||
| 			// note: data-v is unaffected by the timezone interpretation
 | ||||
| 			if(cell.v != null) sp["data-v"] = escapehtml(cell.v instanceof Date ? cell.v.toISOString() : cell.v); | ||||
| 			if(cell.v != null) sp["data-v"] = cell.v; | ||||
| 			if(cell.z != null) sp["data-z"] = cell.z; | ||||
| 			if(cell.f != null) sp["data-f"] = escapehtml(cell.f); | ||||
| 			if(cell.l && (cell.l.Target || "#").charAt(0) != "#") w = '<a href="' + escapehtml(cell.l.Target) +'">' + w + '</a>'; | ||||
| 			if(cell.l && (cell.l.Target || "#").charAt(0) != "#") w = '<a href="' + cell.l.Target +'">' + w + '</a>'; | ||||
| 		} | ||||
| 		sp.id = (o.id || "sjs") + "-" + coord; | ||||
| 		oo.push(writextag('td', w, sp)); | ||||
| @ -106,7 +95,7 @@ var HTML_BEGIN = '<html><head><meta charset="utf-8"/><title>SheetJS Table Export | ||||
| var HTML_END = '</body></html>'; | ||||
| 
 | ||||
| function html_to_workbook(str/*:string*/, opts)/*:Workbook*/ { | ||||
| 	var mtch = str_match_xml_ig(str, "table"); | ||||
| 	var mtch = str.match(/<table[\s\S]*?>[\s\S]*?<\/table>/gi); | ||||
| 	if(!mtch || mtch.length == 0) throw new Error("Invalid HTML: could not find <table>"); | ||||
| 	if(mtch.length == 1) { | ||||
| 		var w = sheet_to_workbook(html_to_sheet(mtch[0], opts), opts); | ||||
| @ -129,9 +118,10 @@ function sheet_to_html(ws/*:Worksheet*/, opts/*:?Sheet2HTMLOpts*//*, wb:?Workboo | ||||
| 	var header = o.header != null ? o.header : HTML_BEGIN; | ||||
| 	var footer = o.footer != null ? o.footer : HTML_END; | ||||
| 	var out/*:Array<string>*/ = [header]; | ||||
| 	var r = decode_range(ws['!ref'] || "A1"); | ||||
| 	var r = decode_range(ws['!ref']); | ||||
| 	o.dense = Array.isArray(ws); | ||||
| 	out.push(make_html_preamble(ws, r, o)); | ||||
| 	if(ws["!ref"]) for(var R = r.s.r; R <= r.e.r; ++R) out.push(make_html_row(ws, r, R, o)); | ||||
| 	for(var R = r.s.r; R <= r.e.r; ++R) out.push(make_html_row(ws, r, R, o)); | ||||
| 	out.push("</table>" + footer); | ||||
| 	return out.join(""); | ||||
| } | ||||
| @ -144,7 +134,7 @@ function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/ | ||||
| 	} | ||||
| 
 | ||||
| 	var opts = _opts || {}; | ||||
| 	var dense = ws["!data"] != null; | ||||
| 	if(DENSE != null) opts.dense = DENSE; | ||||
| 	var or_R = 0, or_C = 0; | ||||
| 	if(opts.origin != null) { | ||||
| 		if(typeof opts.origin == 'number') or_R = opts.origin; | ||||
| @ -180,7 +170,6 @@ function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/ | ||||
| 			if (opts.display && is_dom_element_hidden(elt)) continue; | ||||
| 			var v/*:?string*/ = elt.hasAttribute('data-v') ? elt.getAttribute('data-v') : elt.hasAttribute('v') ? elt.getAttribute('v') : htmldecode(elt.innerHTML); | ||||
| 			var z/*:?string*/ = elt.getAttribute('data-z') || elt.getAttribute('z'); | ||||
| 			var f/*:?string*/ = elt.hasAttribute('data-f') ? elt.getAttribute('data-f') : elt.hasAttribute('f') ? elt.getAttribute('f') : null; | ||||
| 			for(midx = 0; midx < merges.length; ++midx) { | ||||
| 				var m/*:Range*/ = merges[midx]; | ||||
| 				if(m.s.c == C + or_C && m.s.r < R + or_R && R + or_R <= m.e.r) { C = m.e.c+1 - or_C; midx = -1; } | ||||
| @ -193,16 +182,14 @@ function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/ | ||||
| 			if(v != null) { | ||||
| 				if(v.length == 0) o.t = _t || 'z'; | ||||
| 				else if(opts.raw || v.trim().length == 0 || _t == "s"){} | ||||
| 				else if(_t == "e" && BErr[+v]) o = {t:'e', v:+v, w: BErr[+v]}; | ||||
| 				else if(v === 'TRUE') o = {t:'b', v:true}; | ||||
| 				else if(v === 'FALSE') o = {t:'b', v:false}; | ||||
| 				else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)}; | ||||
| 				else if(!isNaN(fuzzydate(v).getDate())) { | ||||
| 					o = ({t:'d', v:parseDate(v)}/*:any*/); | ||||
| 					if(opts.UTC) o.v = local_to_utc(o.v); | ||||
| 					if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)}/*:any*/); | ||||
| 					o.z = opts.dateNF || table_fmt[14]; | ||||
| 				} else if(v.charCodeAt(0) == 35 /* # */ && RBErr[v] != null) o = ({t:'e', v: RBErr[v], w: v}); | ||||
| 				} | ||||
| 			} | ||||
| 			if(o.z === undefined && z != null) o.z = z; | ||||
| 			/* The first link is used.  Links are assumed to be fully specified. | ||||
| @ -212,8 +199,7 @@ function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/ | ||||
| 				l = Aelts[Aelti].getAttribute("href"); if(l.charAt(0) != "#") break; | ||||
| 			} | ||||
| 			if(l && l.charAt(0) != "#" &&	l.slice(0, 11).toLowerCase() != 'javascript:') o.l = ({ Target: l }); | ||||
| 			if(f != null) o.f = f; | ||||
| 			if(dense) { if(!ws["!data"][R + or_R]) ws["!data"][R + or_R] = []; ws["!data"][R + or_R][C + or_C] = o; } | ||||
| 			if(opts.dense) { if(!ws[R + or_R]) ws[R + or_R] = []; ws[R + or_R][C + or_C] = o; } | ||||
| 			else ws[encode_cell({c:C + or_C, r:R + or_R})] = o; | ||||
| 			if(range.e.c < C + or_C) range.e.c = C + or_C; | ||||
| 			C += CS; | ||||
| @ -229,7 +215,7 @@ function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/ | ||||
| 
 | ||||
| function parse_dom_table(table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ { | ||||
| 	var opts = _opts || {}; | ||||
| 	var ws/*:Worksheet*/ = ({}/*:any*/); if(opts.dense) ws["!data"] = []; | ||||
| 	var ws/*:Worksheet*/ = opts.dense ? ([]/*:any*/) : ({}/*:any*/); | ||||
| 	return sheet_add_dom(ws, table, _opts); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -5,9 +5,9 @@ function parse_text_p(text/*:string*//*::, tag*/)/*:Array<any>*/ { | ||||
| 		.replace(/[\t\r\n]/g, " ").trim().replace(/ +/g, " ") | ||||
| 		.replace(/<text:s\/>/g," ") | ||||
| 		.replace(/<text:s text:c="(\d+)"\/>/g, function($$,$1) { return Array(parseInt($1,10)+1).join(" "); }) | ||||
| 		.replace(/<text:tab[^<>]*\/>/g,"\t") | ||||
| 		.replace(/<text:tab[^>]*\/>/g,"\t") | ||||
| 		.replace(/<text:line-break\/>/g,"\n"); | ||||
| 	var v = unescapexml(fixed.replace(/<[^<>]*>/g,"")); | ||||
| 	var v = unescapexml(fixed.replace(/<[^>]*>/g,"")); | ||||
| 
 | ||||
| 	return [v]; | ||||
| } | ||||
| @ -17,10 +17,10 @@ function parse_ods_styles(d/*:string*/, _opts, _nfm) { | ||||
| 	var number_format_map = _nfm || {}; | ||||
| 	var str = xlml_normalize(d); | ||||
| 	xlmlregex.lastIndex = 0; | ||||
| 	str = remove_doctype(str_remove_ng(str, "<!--", "-->")); | ||||
| 	str = str.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,""); | ||||
| 	var Rn, NFtag, NF = "", tNF = "", y, etpos = 0, tidx = -1, infmt = false, payload = ""; | ||||
| 	while((Rn = xlmlregex.exec(str))) { | ||||
| 		switch((Rn[3]=Rn[3].replace(/_[\s\S]*$/,""))) { | ||||
| 		switch((Rn[3]=Rn[3].replace(/_.*$/,""))) { | ||||
| 		/* Number Format Definitions */ | ||||
| 		case 'number-style': // <number:number-style> 16.29.2
 | ||||
| 		case 'currency-style': // <number:currency-style> 16.29.8
 | ||||
| @ -245,27 +245,28 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ { | ||||
| 		var sheetag/*:: = {name:"", '名称':""}*/; | ||||
| 		var rowtag/*:: = {'行号':""}*/; | ||||
| 		var Sheets = {}, SheetNames/*:Array<string>*/ = []; | ||||
| 		var ws = ({}/*:any*/); if(opts.dense) ws["!data"] = []; | ||||
| 		var ws = opts.dense ? ([]/*:any*/) : ({}/*:any*/); | ||||
| 		var Rn, q/*:: :any = ({t:"", v:null, z:null, w:"",c:[],}:any)*/; | ||||
| 		var ctag = ({value:""}/*:any*/), ctag2 = ({}/*:any*/); | ||||
| 		var textp = "", textpidx = 0, textptag/*:: = {}*/, oldtextp = "", oldtextpidx = 0; | ||||
| 		var textR = [], oldtextR = []; | ||||
| 		var ctag = ({value:""}/*:any*/); | ||||
| 		var textp = "", textpidx = 0, textptag/*:: = {}*/; | ||||
| 		var textR = []; | ||||
| 		var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}}; | ||||
| 		var row_ol = 0; | ||||
| 		var number_format_map = _nfm || {}, styles = {}, tstyles = {}; | ||||
| 		var number_format_map = _nfm || {}, styles = {}; | ||||
| 		var merges/*:Array<Range>*/ = [], mrange = {}, mR = 0, mC = 0; | ||||
| 		var rowinfo/*:Array<RowInfo>*/ = [], rowpeat = 1, colpeat = 1; | ||||
| 		var arrayf/*:Array<[Range, string]>*/ = []; | ||||
| 		var WB = {Names:[], WBProps:{}, Sheets:[]}; | ||||
| 		var WB = {Names:[], WBProps:{}}; | ||||
| 		var atag = ({}/*:any*/); | ||||
| 		var _Ref/*:[string, string]*/ = ["", ""]; | ||||
| 		var comments/*:Array<Comment>*/ = [], comment/*:Comment*/ = ({}/*:any*/); | ||||
| 		var creator = "", creatoridx = 0; | ||||
| 		var isstub = false, intable = false; | ||||
| 		var i = 0; | ||||
| 		var baddate = 0; | ||||
| 		xlmlregex.lastIndex = 0; | ||||
| 		str = remove_doctype(str_remove_ng(str, "<!--", "-->")); | ||||
| 		while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_[\s\S]*$/,""))) { | ||||
| 		str = str.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,""); | ||||
| 		while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_.*$/,""))) { | ||||
| 
 | ||||
| 			case 'table': case '工作表': // 9.1.2 <table:table>
 | ||||
| 				if(Rn[1]==='/') { | ||||
| @ -282,17 +283,13 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ { | ||||
| 					if(typeof JSON !== 'undefined') JSON.stringify(sheetag); | ||||
| 					SheetNames.push(sheetag.name); | ||||
| 					Sheets[sheetag.name] = ws; | ||||
| 					WB.Sheets.push({ | ||||
| 						/* TODO: CodeName */ | ||||
| 						Hidden: (tstyles[sheetag["style-name"]] && tstyles[sheetag["style-name"]]["display"] ? (parsexmlbool(tstyles[sheetag["style-name"]]["display"]) ? 0 : 1) : 0) | ||||
| 					}); | ||||
| 					intable = false; | ||||
| 				} | ||||
| 				else if(Rn[0].charAt(Rn[0].length-2) !== '/') { | ||||
| 					sheetag = parsexmltag(Rn[0], false); | ||||
| 					R = C = -1; | ||||
| 					range.s.r = range.s.c = 10000000; range.e.r = range.e.c = 0; | ||||
| 					ws = ({}/*:any*/); if(opts.dense) ws["!data"] = []; merges = []; | ||||
| 					ws = opts.dense ? ([]/*:any*/) : ({}/*:any*/); merges = []; | ||||
| 					rowinfo = []; | ||||
| 					intable = true; | ||||
| 				} | ||||
| @ -310,18 +307,10 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ { | ||||
| 				if(rowpeat < 10) for(i = 0; i < rowpeat; ++i) if(row_ol > 0) rowinfo[R + i] = {level: row_ol}; | ||||
| 				C = -1; break; | ||||
| 			case 'covered-table-cell': // 9.1.5 <table:covered-table-cell>
 | ||||
| 				if(Rn[1] !== '/') { | ||||
| 					++C; | ||||
| 					ctag = parsexmltag(Rn[0], false); | ||||
| 					colpeat = parseInt(ctag['number-columns-repeated']||"1",10) || 1; | ||||
| 					if(opts.sheetStubs) { | ||||
| 						while(colpeat-- > 0) { | ||||
| 							if(opts.dense) { if(!ws["!data"][R]) ws["!data"][R] = []; ws["!data"][R][C] = {t:'z'}; } | ||||
| 							else ws[encode_cell({r:R,c:C})] = {t:'z'}; | ||||
| 							++C; | ||||
| 						} --C; | ||||
| 					} | ||||
| 					else C += colpeat - 1; | ||||
| 				if(Rn[1] !== '/') ++C; | ||||
| 				if(opts.sheetStubs) { | ||||
| 					if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = {t:'z'}; } | ||||
| 					else ws[encode_cell({r:R,c:C})] = {t:'z'}; | ||||
| 				} | ||||
| 				textp = ""; textR = []; | ||||
| 				break; /* stub */ | ||||
| @ -329,23 +318,23 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ { | ||||
| 				if(Rn[0].charAt(Rn[0].length-2) === '/') { | ||||
| 					++C; | ||||
| 					ctag = parsexmltag(Rn[0], false); | ||||
| 					colpeat = parseInt(ctag['number-columns-repeated']||"1", 10)||1; | ||||
| 					colpeat = parseInt(ctag['number-columns-repeated']||"1", 10); | ||||
| 					q = ({t:'z', v:null/*:: , z:null, w:"",c:[]*/}/*:any*/); | ||||
| 					if(ctag.formula && opts.cellFormula != false) q.f = ods_to_csf_formula(unescapexml(ctag.formula)); | ||||
| 					if(ctag["style-name"] && styles[ctag["style-name"]]) q.z = styles[ctag["style-name"]]; | ||||
| 					if((ctag['数据类型'] || ctag['value-type']) == "string") { | ||||
| 						q.t = "s"; q.v = unescapexml(ctag['string-value'] || ""); | ||||
| 						if(opts.dense) { | ||||
| 							if(!ws["!data"][R]) ws["!data"][R] = []; | ||||
| 							ws["!data"][R][C] = q; | ||||
| 							if(!ws[R]) ws[R] = []; | ||||
| 							ws[R][C] = q; | ||||
| 						} else { | ||||
| 							ws[encode_col(C) + encode_row(R)] = q; | ||||
| 							ws[encode_cell({r:R,c:C})] = q; | ||||
| 						} | ||||
| 					} | ||||
| 					C+= colpeat-1; | ||||
| 				} else if(Rn[1]!=='/') { | ||||
| 					++C; | ||||
| 					textp = oldtextp = ""; textpidx = oldtextpidx = 0; textR = []; oldtextR = []; | ||||
| 					textp = ""; textpidx = 0; textR = []; | ||||
| 					colpeat = 1; | ||||
| 					var rptR = rowpeat ? R + rowpeat - 1 : R; | ||||
| 					if(C > range.e.c) range.e.c = C; | ||||
| @ -353,7 +342,6 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ { | ||||
| 					if(R < range.s.r) range.s.r = R; | ||||
| 					if(rptR > range.e.r) range.e.r = rptR; | ||||
| 					ctag = parsexmltag(Rn[0], false); | ||||
| 					ctag2 = parsexmltagraw(Rn[0], true); | ||||
| 					comments = []; comment = ({}/*:any*/); | ||||
| 					q = ({t:ctag['数据类型'] || ctag['value-type'], v:null/*:: , z:null, w:"",c:[]*/}/*:any*/); | ||||
| 					if(ctag["style-name"] && styles[ctag["style-name"]]) q.z = styles[ctag["style-name"]]; | ||||
| @ -373,34 +361,28 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ { | ||||
| 									q.F = arrayf[i][1]; | ||||
| 					} | ||||
| 					if(ctag['number-columns-spanned'] || ctag['number-rows-spanned']) { | ||||
| 						mR = parseInt(ctag['number-rows-spanned']||"1",10) || 1; | ||||
| 						mC = parseInt(ctag['number-columns-spanned']||"1",10) || 1; | ||||
| 						if(mR * mC > 1) { | ||||
| 							mrange = {s: {r:R,c:C}, e:{r:R + mR-1,c:C + mC-1}}; | ||||
| 							merges.push(mrange); | ||||
| 						} | ||||
| 						mR = parseInt(ctag['number-rows-spanned'],10) || 0; | ||||
| 						mC = parseInt(ctag['number-columns-spanned'],10) || 0; | ||||
| 						mrange = {s: {r:R,c:C}, e:{r:R + mR-1,c:C + mC-1}}; | ||||
| 						merges.push(mrange); | ||||
| 					} | ||||
| 
 | ||||
| 					/* 19.675.2 table:number-columns-repeated */ | ||||
| 					if(ctag['number-columns-repeated']) colpeat = parseInt(ctag['number-columns-repeated'], 10); | ||||
| 
 | ||||
| 					/* 19.385 office:value-type TODO: verify ODS and UOS */ | ||||
| 					/* 19.385 office:value-type */ | ||||
| 					switch(q.t) { | ||||
| 						case 'boolean': q.t = 'b'; q.v = parsexmlbool(ctag['boolean-value']) || (+ctag['boolean-value'] >= 1); break; | ||||
| 						case 'float': q.t = 'n'; q.v = parseFloat(ctag.value); | ||||
| 							if(opts.cellDates && q.z && fmt_is_date(q.z)) { q.v = numdate(q.v + (WB.WBProps.date1904 ? 1462 : 0)); q.t = typeof q.v == "number" ? 'n' : 'd'; } | ||||
| 							break; | ||||
| 						case 'float': q.t = 'n'; q.v = parseFloat(ctag.value); break; | ||||
| 						case 'percentage': q.t = 'n'; q.v = parseFloat(ctag.value); break; | ||||
| 						case 'currency': q.t = 'n'; q.v = parseFloat(ctag.value); break; | ||||
| 						case 'date': q.t = 'd'; q.v = parseDate(ctag['date-value'], WB.WBProps.date1904); | ||||
| 							if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v, WB.WBProps.date1904); } | ||||
| 						case 'date': q.t = 'd'; q.v = parseDate(ctag['date-value']); | ||||
| 							if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v, WB.WBProps.date1904) - baddate; } | ||||
| 							if(!q.z) q.z = 'm/d/yy'; break; | ||||
| 						/* NOTE: for `time`, Excel ODS export incorrectly uses durations relative to 1900 epoch even if 1904 is specified */ | ||||
| 						case 'time': q.t = 'n'; q.v = parse_isodur(ctag['time-value'])/86400; | ||||
| 							if(opts.cellDates) { q.v = numdate(q.v); q.t = typeof q.v == "number" ? 'n' : 'd'; } | ||||
| 							if(opts.cellDates) { q.t = 'd'; q.v = numdate(q.v); } | ||||
| 							if(!q.z) q.z = 'HH:MM:SS'; break; | ||||
| 						case 'number': q.t = 'n'; q.v = parseFloat(ctag['数据数值']); | ||||
| 							break; | ||||
| 						case 'number': q.t = 'n'; q.v = parseFloat(ctag['数据数值']); break; | ||||
| 						default: | ||||
| 							if(q.t === 'string' || q.t === 'text' || !q.t) { | ||||
| 								q.t = 's'; | ||||
| @ -409,9 +391,6 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ { | ||||
| 					} | ||||
| 				} else { | ||||
| 					isstub = false; | ||||
| 					if(ctag2['calcext:value-type'] == "error" && RBErr[textp] != null) { | ||||
| 						q.t = 'e'; q.w = textp; q.v = RBErr[textp]; | ||||
| 					} | ||||
| 					if(q.t === 's') { | ||||
| 						q.v = textp || ''; | ||||
| 						if(textR.length) q.R = textR; | ||||
| @ -426,9 +405,9 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ { | ||||
| 							for(var rpt = 0; rpt < rowpeat; ++rpt) { | ||||
| 								colpeat = parseInt(ctag['number-columns-repeated']||"1", 10); | ||||
| 								if(opts.dense) { | ||||
| 									if(!ws["!data"][R + rpt]) ws["!data"][R + rpt] = []; | ||||
| 									ws["!data"][R + rpt][C] = rpt == 0 ? q : dup(q); | ||||
| 									while(--colpeat > 0) ws["!data"][R + rpt][C + colpeat] = dup(q); | ||||
| 									if(!ws[R + rpt]) ws[R + rpt] = []; | ||||
| 									ws[R + rpt][C] = rpt == 0 ? q : dup(q); | ||||
| 									while(--colpeat > 0) ws[R + rpt][C + colpeat] = dup(q); | ||||
| 								} else { | ||||
| 									ws[encode_cell({r:R + rpt,c:C})] = q; | ||||
| 									while(--colpeat > 0) ws[encode_cell({r:R + rpt,c:C + colpeat})] = dup(q); | ||||
| @ -464,17 +443,10 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ { | ||||
| 					if(textR.length) /*::(*/comment/*:: :any)*/.R = textR; | ||||
| 					comment.a = creator; | ||||
| 					comments.push(comment); | ||||
| 					textp = oldtextp; textpidx = oldtextpidx; textR = oldtextR; | ||||
| 				} | ||||
| 				else if(Rn[0].charAt(Rn[0].length-2) !== '/') { | ||||
| 					state.push([Rn[3], false]); | ||||
| 					var annotag = parsexmltag(Rn[0], true); | ||||
| 					/* office:display TODO: check if there is a global override */ | ||||
| 					if(!(annotag["display"] && parsexmlbool(annotag["display"]))) comments.hidden = true; | ||||
| 					oldtextp = textp; oldtextpidx = textpidx; oldtextR = textR; | ||||
| 					textp = ""; textpidx = 0; textR = []; | ||||
| 				} | ||||
| 				else if(Rn[0].charAt(Rn[0].length-2) !== '/') {state.push([Rn[3], false]);} | ||||
| 				creator = ""; creatoridx = 0; | ||||
| 				textp = ""; textpidx = 0; textR = []; | ||||
| 				break; | ||||
| 
 | ||||
| 			case 'creator': // 4.3.2.7 <dc:creator>
 | ||||
| @ -533,16 +505,12 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ { | ||||
| 			case 'style': { // 16.2 <style:style>
 | ||||
| 				var styletag = parsexmltag(Rn[0], false); | ||||
| 				if(styletag["family"] == "table-cell" && number_format_map[styletag["data-style-name"]]) styles[styletag["name"]] = number_format_map[styletag["data-style-name"]]; | ||||
| 				else if(styletag["family"] == "table") tstyles[styletag["name"]] = styletag; | ||||
| 			} break; | ||||
| 			case 'map': break; // 16.3 <style:map>
 | ||||
| 			case 'font-face': break; // 16.21 <style:font-face>
 | ||||
| 
 | ||||
| 			case 'paragraph-properties': break; // 17.6 <style:paragraph-properties>
 | ||||
| 			case 'table-properties': { // 17.15 <style:table-properties>
 | ||||
| 				var proptag = parsexmltag(Rn[0], false); | ||||
| 				if(styletag && styletag.family == "table") styletag.display = proptag.display; | ||||
| 			} break; | ||||
| 			case 'table-properties': break; // 17.15 <style:table-properties>
 | ||||
| 			case 'table-column-properties': break; // 17.16 <style:table-column-properties>
 | ||||
| 			case 'table-row-properties': break; // 17.17 <style:table-row-properties>
 | ||||
| 			case 'table-cell-properties': break; // 17.18 <style:table-cell-properties>
 | ||||
| @ -604,7 +572,9 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ { | ||||
| 			case 'null-date': // 9.4.2 <table:null-date>
 | ||||
| 				tag = parsexmltag(Rn[0], false); | ||||
| 				switch(tag["date-value"]) { | ||||
| 					case "1904-01-01": WB.WBProps.date1904 = true; break; | ||||
| 					case "1904-01-01": WB.WBProps.date1904 = true; | ||||
| 					/* falls through */ | ||||
| 					case "1900-01-01": baddate = 0; | ||||
| 				} | ||||
| 				break; | ||||
| 
 | ||||
| @ -626,9 +596,6 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ { | ||||
| 				if(Rn[1]==='/' && (!ctag || !ctag['string-value'])) { | ||||
| 					var ptp = parse_text_p(str.slice(textpidx,Rn.index), textptag); | ||||
| 					textp = (textp.length > 0 ? textp + "\n" : "") + ptp[0]; | ||||
| 				} else if(Rn[0].slice(-2) == "/>") { | ||||
| 					/* TODO: is self-closing 文本串 valid? */ | ||||
| 					textp += "\n"; | ||||
| 				} else { textptag = parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; } | ||||
| 				break; // <text:p>
 | ||||
| 			case 's': break; // <text:s>
 | ||||
| @ -658,13 +625,10 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ { | ||||
| 			case 'help-message': break; // 9.4.6 <table:
 | ||||
| 			case 'error-message': break; // 9.4.7 <table:
 | ||||
| 			case 'database-ranges': break; // 9.4.14 <table:database-ranges>
 | ||||
| 
 | ||||
| 			/* 9.5 Filters */ | ||||
| 			case 'filter': break; // 9.5.2 <table:filter>
 | ||||
| 			case 'filter-and': break; // 9.5.3 <table:filter-and>
 | ||||
| 			case 'filter-or': break; // 9.5.4 <table:filter-or>
 | ||||
| 			case 'filter-condition': break; // 9.5.5 <table:filter-condition>
 | ||||
| 			case 'filter-set-item': break; // 9.5.6 <table:filter-condition>
 | ||||
| 
 | ||||
| 			case 'list-level-style-bullet': break; // 16.31 <text:
 | ||||
| 			case 'list-level-style-number': break; // 16.32 <text:
 | ||||
| @ -814,3 +778,4 @@ function parse_fods(data/*:string*/, opts/*:?ParseOpts*/)/*:Workbook*/ { | ||||
| 	wb.bookType = "fods"; | ||||
| 	return wb; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -67,7 +67,7 @@ function write_number_format_ods(nf/*:string*/, nfidx/*:string*/)/*:string*/ { | ||||
| 		if((t=nf.match(/# (\?+)\/(\d+)/))) { payload += writextag("number:fraction", null, {"number:min-integer-digits":0, "number:min-numerator-digits": t[1].length, "number:denominator-value": +t[2]}); break j; } | ||||
| 
 | ||||
| 		/* percentages */ | ||||
| 		if((t=nf.match(/\b(\d+)(|\.\d+)%/))) { type = "percentage"; payload += writextag("number:number", null, {"number:decimal-places": t[2] && t.length - 1 || 0, "number:min-decimal-places": t[2] && t.length - 1 || 0, "number:min-integer-digits": t[1].length }) + "<number:text>%</number:text>"; break j; } | ||||
| 		if((t=nf.match(/(\d+)(|\.\d+)%/))) { type = "percentage"; payload += writextag("number:number", null, {"number:decimal-places": t[2] && t.length - 1 || 0, "number:min-decimal-places": t[2] && t.length - 1 || 0, "number:min-integer-digits": t[1].length }) + "<number:text>%</number:text>"; break j; } | ||||
| 
 | ||||
| 		/* datetime */ | ||||
| 		var has_time = false; | ||||
| @ -99,9 +99,7 @@ function write_number_format_ods(nf/*:string*/, nfidx/*:string*/)/*:string*/ { | ||||
| 					while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i; | ||||
| 					payload += '<number:text>' + escapexml(c.slice(1).replace(/""/g, '"')) + '</number:text>'; | ||||
| 					break; | ||||
| 				case '\\': c = nf[++i]; | ||||
| 					payload += '<number:text>' + escapexml(c) + '</number:text>'; break; | ||||
| 				case '/': case ':': payload += '<number:text>' + escapexml(c) + '</number:text>'; break; | ||||
| 				case '/': payload += '<number:text>' + escapexml(c) + '</number:text>'; break; | ||||
| 				default: console.error("unrecognized character " + c + " in ODF format " + nf); | ||||
| 			} | ||||
| 			if(!has_time) break j; | ||||
| @ -128,7 +126,7 @@ function write_number_format_ods(nf/*:string*/, nfidx/*:string*/)/*:string*/ { | ||||
| 					while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i; | ||||
| 					payload += '<number:text>' + escapexml(c.slice(1).replace(/""/g, '"')) + '</number:text>'; | ||||
| 					break; | ||||
| 				case '/': case ':': payload += '<number:text>' + escapexml(c) + '</number:text>'; break; | ||||
| 				case '/': payload += '<number:text>' + escapexml(c) + '</number:text>'; break; | ||||
| 				case "a": | ||||
| 					if(nf.slice(i, i+3).toLowerCase() == "a/p") { payload += '<number:am-pm/>'; i += 2; break; } // Note: ODF does not support A/P
 | ||||
| 					if(nf.slice(i, i+5).toLowerCase() == "am/pm")  { payload += '<number:am-pm/>'; i += 4; break; } | ||||
| @ -184,42 +182,36 @@ function write_number_format_ods(nf/*:string*/, nfidx/*:string*/)/*:string*/ { | ||||
| } | ||||
| 
 | ||||
| function write_names_ods(Names, SheetNames, idx) { | ||||
| 	//var scoped = Names.filter(function(name) { return name.Sheet == (idx == -1 ? null : idx); });
 | ||||
| 	var scoped = []; for(var namei = 0; namei < Names.length; ++namei) { | ||||
| 		var name = Names[namei]; | ||||
| 		if(!name) continue; | ||||
| 		if(name.Sheet == (idx == -1 ? null : idx)) scoped.push(name); | ||||
| 	} | ||||
| 	var scoped = Names.filter(function(name) { return name.Sheet == (idx == -1 ? null : idx); }); | ||||
| 	if(!scoped.length) return ""; | ||||
| 	return "      <table:named-expressions>\n" + scoped.map(function(name) { | ||||
| 		var odsref =  (idx == -1 ? "$" : "") + csf_to_ods_3D(name.Ref); | ||||
| 		var odsref =  csf_to_ods_3D(name.Ref); | ||||
| 		return "        " + writextag("table:named-range", null, { | ||||
| 			"table:name": name.Name, | ||||
| 			"table:cell-range-address": odsref, | ||||
| 			"table:base-cell-address": odsref.replace(/[\.][^\.]*$/, ".$A$1") | ||||
| 			"table:base-cell-address": odsref.replace(/[\.]?[^\.]*$/, ".$A$1") | ||||
| 		}); | ||||
| 	}).join("\n") + "\n      </table:named-expressions>\n"; | ||||
| } | ||||
| var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function() { | ||||
| 	/* 6.1.2 White Space Characters */ | ||||
| 	var write_text_p = function(text/*:string*/, span)/*:string*/ { | ||||
| 	var write_text_p = function(text/*:string*/)/*:string*/ { | ||||
| 		return escapexml(text) | ||||
| 			.replace(/  +/g, function($$){return '<text:s text:c="'+$$.length+'"/>';}) | ||||
| 			.replace(/\t/g, "<text:tab/>") | ||||
| 			.replace(/\n/g, span ? "<text:line-break/>": "</text:p><text:p>") | ||||
| 			.replace(/\n/g, "</text:p><text:p>") | ||||
| 			.replace(/^ /, "<text:s/>").replace(/ $/, "<text:s/>"); | ||||
| 	}; | ||||
| 
 | ||||
| 	var null_cell_xml = '          <table:table-cell />\n'; | ||||
| 	var write_ws = function(ws, wb/*:Workbook*/, i/*:number*/, opts, nfs, date1904)/*:string*/ { | ||||
| 	var covered_cell_xml = '          <table:covered-table-cell/>\n'; | ||||
| 	var write_ws = function(ws, wb/*:Workbook*/, i/*:number*/, opts, nfs)/*:string*/ { | ||||
| 		/* Section 9 Tables */ | ||||
| 		var o/*:Array<string>*/ = []; | ||||
| 		var tstyle = "ta1"; | ||||
| 		if(((((wb||{}).Workbook||{}).Sheets||[])[i]||{}).Hidden) tstyle = "ta2"; | ||||
| 		o.push('      <table:table table:name="' + escapexml(wb.SheetNames[i]) + '" table:style-name="' + tstyle + '">\n'); | ||||
| 		o.push('      <table:table table:name="' + escapexml(wb.SheetNames[i]) + '" table:style-name="ta1">\n'); | ||||
| 		var R=0,C=0, range = decode_range(ws['!ref']||"A1"); | ||||
| 		var marr/*:Array<Range>*/ = ws['!merges'] || [], mi = 0; | ||||
| 		var dense = ws["!data"] != null; | ||||
| 		var dense = Array.isArray(ws); | ||||
| 		if(ws["!cols"]) { | ||||
| 			for(C = 0; C <= range.e.c; ++C) o.push('        <table:table-column' + (ws["!cols"][C] ? ' table:style-name="co' + ws["!cols"][C].ods + '"' : '') + '></table:table-column>\n'); | ||||
| 		} | ||||
| @ -244,8 +236,8 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function | ||||
| 					ct['table:number-rows-spanned'] =    (marr[mi].e.r - marr[mi].s.r + 1); | ||||
| 					break; | ||||
| 				} | ||||
| 				if(skip) { o.push('          <table:covered-table-cell/>\n'); continue; } | ||||
| 				var ref = encode_cell({r:R, c:C}), cell = dense ? (ws["!data"][R]||[])[C]: ws[ref]; | ||||
| 				if(skip) { o.push(covered_cell_xml); continue; } | ||||
| 				var ref = encode_cell({r:R, c:C}), cell = dense ? (ws[R]||[])[C]: ws[ref]; | ||||
| 				if(cell && cell.f) { | ||||
| 					ct['table:formula'] = escapexml(csf_to_ods_formula(cell.f)); | ||||
| 					if(cell.F) { | ||||
| @ -264,35 +256,22 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function | ||||
| 						ct['office:boolean-value'] = (cell.v ? 'true' : 'false'); | ||||
| 						break; | ||||
| 					case 'n': | ||||
| 						if(!isFinite(cell.v)) { | ||||
| 							if(isNaN(cell.v)) { | ||||
| 								textp = "#NUM!"; | ||||
| 								ct['table:formula'] = "of:=#NUM!"; | ||||
| 							} else { | ||||
| 								textp = "#DIV/0!"; | ||||
| 								ct['table:formula'] = "of:=" + (cell.v < 0 ? "-" : "") + "1/0"; | ||||
| 							} | ||||
| 							ct['office:string-value'] = ""; | ||||
| 							ct['office:value-type'] = "string"; | ||||
| 							ct['calcext:value-type'] = "error"; | ||||
| 						} else { | ||||
| 							textp = (cell.w||String(cell.v||0)); | ||||
| 							ct['office:value-type'] = "float"; | ||||
| 							ct['office:value'] = (cell.v||0); | ||||
| 						} | ||||
| 						textp = (cell.w||String(cell.v||0)); | ||||
| 						ct['office:value-type'] = "float"; | ||||
| 						ct['office:value'] = (cell.v||0); | ||||
| 						break; | ||||
| 					case 's': case 'str': | ||||
| 						textp = cell.v == null ? "" : cell.v; | ||||
| 						ct['office:value-type'] = "string"; | ||||
| 						break; | ||||
| 					case 'd': | ||||
| 						textp = (cell.w||(parseDate(cell.v, date1904).toISOString())); | ||||
| 						textp = (cell.w||(parseDate(cell.v).toISOString())); | ||||
| 						ct['office:value-type'] = "date"; | ||||
| 						ct['office:date-value'] = (parseDate(cell.v, date1904).toISOString()); | ||||
| 						ct['office:date-value'] = (parseDate(cell.v).toISOString()); | ||||
| 						ct['table:style-name'] = "ce1"; | ||||
| 						break; | ||||
| 					//case 'e': // TODO: translate to ODS errors
 | ||||
| 					default: o.push(null_cell_xml); continue; // TODO: empty cell with comments
 | ||||
| 					//case 'e':
 | ||||
| 					default: o.push(null_cell_xml); continue; | ||||
| 				} | ||||
| 				var text_p = write_text_p(textp); | ||||
| 				if(cell.l && cell.l.Target) { | ||||
| @ -303,17 +282,7 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function | ||||
| 					text_p = writextag('text:a', text_p, {'xlink:href': _tgt.replace(/&/g, "&")}); | ||||
| 				} | ||||
| 				if(nfs[cell.z]) ct["table:style-name"] = "ce" + nfs[cell.z].slice(1); | ||||
| 				var payload = writextag('text:p', text_p, {}); | ||||
| 				if(cell.c) { | ||||
| 					var acreator = "", apayload = "", aprops = {}; | ||||
| 					for(var ci = 0; ci < cell.c.length; ++ci) { | ||||
| 						if(!acreator && cell.c[ci].a) acreator = cell.c[ci].a; | ||||
| 						apayload += "<text:p>" + write_text_p(cell.c[ci].t) + "</text:p>"; | ||||
| 					} | ||||
| 					if(!cell.c.hidden) aprops["office:display"] = true; | ||||
| 					payload = writextag('office:annotation', apayload, aprops) + payload; | ||||
| 				} | ||||
| 				o.push('          ' + writextag('table:table-cell', payload, ct) + '\n'); | ||||
| 				o.push('          ' + writextag('table:table-cell', writextag('text:p', text_p, {}), ct) + '\n'); | ||||
| 			} | ||||
| 			o.push('        </table:table-row>\n'); | ||||
| 		} | ||||
| @ -364,9 +333,6 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function | ||||
| 		o.push('  <style:style style:name="ta1" style:family="table" style:master-page-name="mp1">\n'); | ||||
| 		o.push('   <style:table-properties table:display="true" style:writing-mode="lr-tb"/>\n'); | ||||
| 		o.push('  </style:style>\n'); | ||||
| 		o.push('  <style:style style:name="ta2" style:family="table" style:master-page-name="mp1">\n'); | ||||
| 		o.push('   <style:table-properties table:display="false" style:writing-mode="lr-tb"/>\n'); | ||||
| 		o.push('  </style:style>\n'); | ||||
| 
 | ||||
| 		o.push('  <number:date-style style:name="N37" number:automatic-order="true">\n'); | ||||
| 		o.push('   <number:month number:style="long"/>\n'); | ||||
| @ -381,11 +347,9 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function | ||||
| 		var nfi = 69; | ||||
| 		wb.SheetNames.map(function(n) { return wb.Sheets[n]; }).forEach(function(ws) { | ||||
| 			if(!ws) return; | ||||
| 			var dense = (ws["!data"] != null); | ||||
| 			if(!ws["!ref"]) return; | ||||
| 			var range = decode_range(ws["!ref"]); | ||||
| 			for(var R = 0; R <= range.e.r; ++R) for(var C = 0; C <= range.e.c; ++C) { | ||||
| 				var c = dense ? (ws["!data"][R]||[])[C] : ws[encode_cell({r:R,c:C})]; | ||||
| 				var c = Array.isArray(ws) ? (ws[R]||[])[C] : ws[encode_cell({r:R,c:C})]; | ||||
| 				if(!c || !c.z || c.z.toLowerCase() == "general") continue; | ||||
| 				if(!nfs[c.z]) { | ||||
| 					var out = write_number_format_ods(c.z, "N" + nfi); | ||||
| @ -454,7 +418,7 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function | ||||
| 
 | ||||
| 		if(opts.bookType == "fods") { | ||||
| 			o.push('<office:document' + attr + fods + '>\n'); | ||||
| 			o.push(write_meta_ods().replace(/<office:document-meta[^<>]*?>/, "").replace(/<\/office:document-meta>/, "") + "\n"); | ||||
| 			o.push(write_meta_ods().replace(/<office:document-meta.*?>/, "").replace(/<\/office:document-meta>/, "") + "\n"); | ||||
| 			// TODO: settings (equiv of settings.xml for ODS)
 | ||||
| 		} else o.push('<office:document-content' + attr  + '>\n'); | ||||
| 		// o.push('  <office:scripts/>\n');
 | ||||
| @ -462,7 +426,7 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function | ||||
| 		o.push('  <office:body>\n'); | ||||
| 		o.push('    <office:spreadsheet>\n'); | ||||
| 		if(((wb.Workbook||{}).WBProps||{}).date1904) o.push('      <table:calculation-settings table:case-sensitive="false" table:search-criteria-must-apply-to-whole-cell="true" table:use-wildcards="true" table:use-regular-expressions="false" table:automatic-find-labels="false">\n        <table:null-date table:date-value="1904-01-01"/>\n      </table:calculation-settings>\n'); | ||||
| 		for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts, nfs, ((wb.Workbook||{}).WBProps||{}).date1904)); | ||||
| 		for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts, nfs)); | ||||
| 		if((wb.Workbook||{}).Names) o.push(write_names_ods(wb.Workbook.Names, wb.SheetNames, -1)); | ||||
| 		o.push('    </office:spreadsheet>\n'); | ||||
| 		o.push('  </office:body>\n'); | ||||
|  | ||||
							
								
								
									
										2006
									
								
								bits/83_numbers.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										2006
									
								
								bits/83_numbers.js
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -13,13 +13,6 @@ function safe_parse_wbrels(wbrels, sheets) { | ||||
| 	return !wbrels || wbrels.length === 0 ? null : wbrels; | ||||
| } | ||||
| 
 | ||||
| function parse_sheet_legacy_drawing(sheet, type, zip, path, idx, opts, wb, comments) { | ||||
| 	if(!sheet || !sheet['!legdrawel']) return; | ||||
| 	var dfile = resolve_path(sheet['!legdrawel'].Target, path); | ||||
| 	var draw = getzipstr(zip, dfile, true); | ||||
| 	if(draw) parse_vml(utf8read(draw), sheet, comments||[]); | ||||
| } | ||||
| 
 | ||||
| function safe_parse_sheet(zip, path/*:string*/, relsPath/*:string*/, sheet, idx/*:number*/, sheetRels, sheets, stype/*:string*/, opts, wb, themes, styles) { | ||||
| 	try { | ||||
| 		sheetRels[sheet]=parse_rels(getzipstr(zip, relsPath, true), path); | ||||
| @ -43,12 +36,12 @@ function safe_parse_sheet(zip, path/*:string*/, relsPath/*:string*/, sheet, idx/ | ||||
| 		sheets[sheet] = _ws; | ||||
| 
 | ||||
| 		/* scan rels for comments and threaded comments */ | ||||
| 		var comments = [], tcomments = []; | ||||
| 		var tcomments = []; | ||||
| 		if(sheetRels && sheetRels[sheet]) keys(sheetRels[sheet]).forEach(function(n) { | ||||
| 			var dfile = ""; | ||||
| 			if(sheetRels[sheet][n].Type == RELS.CMNT) { | ||||
| 				dfile = resolve_path(sheetRels[sheet][n].Target, path); | ||||
| 				comments = parse_cmnt(getzipdata(zip, dfile, true), dfile, opts); | ||||
| 				var comments = parse_cmnt(getzipdata(zip, dfile, true), dfile, opts); | ||||
| 				if(!comments || !comments.length) return; | ||||
| 				sheet_insert_comments(_ws, comments, false); | ||||
| 			} | ||||
| @ -58,7 +51,6 @@ function safe_parse_sheet(zip, path/*:string*/, relsPath/*:string*/, sheet, idx/ | ||||
| 			} | ||||
| 		}); | ||||
| 		if(tcomments && tcomments.length) sheet_insert_comments(_ws, tcomments, true, opts.people || []); | ||||
| 		parse_sheet_legacy_drawing(_ws, stype, zip, path, idx, opts, wb, comments); | ||||
| 	} catch(e) { if(opts.WTF) throw e; } | ||||
| } | ||||
| 
 | ||||
| @ -204,7 +196,7 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ { | ||||
| 		if(wbrels && wbrels[i]) { | ||||
| 			path = 'xl/' + (wbrels[i][1]).replace(/[\/]?xl\//, ""); | ||||
| 			if(!safegetzipfile(zip, path)) path = wbrels[i][1]; | ||||
| 			if(!safegetzipfile(zip, path)) path = wbrelsfile.replace(/_rels\/[\S\s]*$/,"") + wbrels[i][1]; | ||||
| 			if(!safegetzipfile(zip, path)) path = wbrelsfile.replace(/_rels\/.*$/,"") + wbrels[i][1]; | ||||
| 			stype = wbrels[i][2]; | ||||
| 		} else { | ||||
| 			path = 'xl/worksheets/sheet'+(i+1-nmode)+"." + wbext; | ||||
| @ -257,7 +249,7 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ { | ||||
| 		if(dir.vba.length > 0) out.vbaraw = getzipdata(zip,strip_front_slash(dir.vba[0]),true); | ||||
| 		else if(dir.defaults && dir.defaults.bin === CT_VBA) out.vbaraw = getzipdata(zip, 'xl/vbaProject.bin',true); | ||||
| 	} | ||||
| 	// TODO: pass back content types metadata for xlsm/xlsx resolution
 | ||||
| 	// TODO: pass back content types metdata for xlsm/xlsx resolution
 | ||||
| 	out.bookType = xlsb ? "xlsb" : "xlsx"; | ||||
| 	return out; | ||||
| } | ||||
|  | ||||
| @ -51,9 +51,6 @@ function write_zip_xlsb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ { | ||||
| 		add_rels(opts.rels, 4, f, RELS.CUST_PROPS); | ||||
| 	} | ||||
| 
 | ||||
| 	var people = ["SheetJ5"]; | ||||
| 	opts.tcid = 0; | ||||
| 
 | ||||
| 	for(rId=1;rId <= wb.SheetNames.length; ++rId) { | ||||
| 		var wsrels = {'!id':{}}; | ||||
| 		var ws = wb.Sheets[wb.SheetNames[rId-1]]; | ||||
| @ -73,17 +70,6 @@ function write_zip_xlsb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ { | ||||
| 			var need_vml = false; | ||||
| 			var cf = ""; | ||||
| 			if(comments && comments.length > 0) { | ||||
| 				var needtc = false; | ||||
| 				comments.forEach(function(carr) { | ||||
| 					carr[1].forEach(function(c) { if(c.T == true) needtc = true; }); | ||||
| 				}); | ||||
| 				if(needtc) { | ||||
| 					cf = "xl/threadedComments/threadedComment" + rId + ".xml"; | ||||
| 					zip_add_file(zip, cf, write_tcmnt_xml(comments, people, opts)); | ||||
| 					ct.threadedcomments.push(cf); | ||||
| 					add_rels(wsrels, -1, "../threadedComments/threadedComment" + rId + ".xml", RELS.TCMNT); | ||||
| 				} | ||||
| 
 | ||||
| 				cf = "xl/comments" + rId + "." + wbext; | ||||
| 				zip_add_file(zip, cf, write_comments_bin(comments, opts)); | ||||
| 				ct.comments.push(cf); | ||||
| @ -115,8 +101,7 @@ function write_zip_xlsb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ { | ||||
| 	/* TODO: something more intelligent with themes */ | ||||
| 
 | ||||
| 	f = "xl/theme/theme1.xml"; | ||||
| 	var ww = write_theme(wb.Themes, opts); | ||||
| 	zip_add_file(zip, f, ww); | ||||
| 	zip_add_file(zip, f, write_theme(wb.Themes, opts)); | ||||
| 	ct.themes.push(f); | ||||
| 	add_rels(opts.wbrels, -1, "theme/theme1.xml", RELS.THEME); | ||||
| 
 | ||||
| @ -139,13 +124,6 @@ function write_zip_xlsb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ { | ||||
| 	ct.metadata.push(f); | ||||
| 	add_rels(opts.wbrels, -1, "metadata." + wbext, RELS.XLMETA); | ||||
| 
 | ||||
| 	if(people.length > 1) { | ||||
| 		f = "xl/persons/person.xml"; | ||||
| 		zip_add_file(zip, f, write_people_xml(people, opts)); | ||||
| 		ct.people.push(f); | ||||
| 		add_rels(opts.wbrels, -1, "persons/person.xml", RELS.PEOPLE); | ||||
| 	} | ||||
| 
 | ||||
| 	zip_add_file(zip, "[Content_Types].xml", write_ct(ct, opts)); | ||||
| 	zip_add_file(zip, '_rels/.rels', write_rels(opts.rels)); | ||||
| 	zip_add_file(zip, 'xl/_rels/workbook.' + wbext + '.rels', write_rels(opts.wbrels)); | ||||
|  | ||||
| @ -50,13 +50,7 @@ function read_plaintext_raw(data/*:RawData*/, o/*:ParseOpts*/)/*:Workbook*/ { | ||||
| function read_utf16(data/*:RawData*/, o/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 	var d = data; | ||||
| 	if(o.type == 'base64') d = Base64_decode(d); | ||||
| 	if(typeof ArrayBuffer !== "undefined" && data instanceof ArrayBuffer) d = new Uint8Array(data); | ||||
| 	d = typeof $cptable !== "undefined" ? $cptable.utils.decode(1200, d.slice(2), 'str') : ( | ||||
| 		(has_buf && Buffer.isBuffer(data)) ? data.slice(2).toString("utf16le") : | ||||
| 		(typeof Uint8Array !== "undefined" && d instanceof Uint8Array) ? ( | ||||
| 			typeof TextDecoder !== "undefined" ? new TextDecoder("utf-16le").decode(d.slice(2)) : utf16lereadu(d.slice(2)) | ||||
| 		) : utf16leread(d.slice(2)) | ||||
| 	); | ||||
| 	d = typeof $cptable !== "undefined" ? $cptable.utils.decode(1200, d.slice(2), 'str') : utf16leread(d.slice(2)); | ||||
| 	o.type = "binary"; | ||||
| 	return read_plaintext(d, o); | ||||
| } | ||||
| @ -75,8 +69,6 @@ function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ { | ||||
| 	var o = opts||{}; | ||||
| 	if(o.codepage && typeof $cptable === "undefined") console.error("Codepage tables are not loaded.  Non-ASCII characters may not give expected results"); | ||||
| 	if(typeof ArrayBuffer !== 'undefined' && data instanceof ArrayBuffer) return readSync(new Uint8Array(data), (o = dup(o), o.type = "array", o)); | ||||
| 	/* Javet projects `byte[]` to `Int8Array` */ | ||||
| 	if(typeof Int8Array !== 'undefined' && data instanceof Int8Array) return readSync(new Uint8Array(data.buffer, data.byteOffset, data.length), o); | ||||
| 	if(typeof Uint8Array !== 'undefined' && data instanceof Uint8Array && !o.type) o.type = typeof Deno !== "undefined" ? "buffer" : "array"; | ||||
| 	var d = data, n = [0,0,0,0], str = false; | ||||
| 	if(o.cellStyles) { o.cellNF = true; o.sheetStubs = true; } | ||||
|  | ||||
| @ -4,18 +4,18 @@ type MJRObject = { | ||||
| 	isempty: boolean; | ||||
| }; | ||||
| */ | ||||
| function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Array<string>*/, header/*:number*/, hdr/*:Array<any>*/, o/*:Sheet2JSONOpts*/)/*:MJRObject*/ { | ||||
| function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Array<string>*/, header/*:number*/, hdr/*:Array<any>*/, dense/*:boolean*/, o/*:Sheet2JSONOpts*/)/*:MJRObject*/ { | ||||
| 	var rr = encode_row(R); | ||||
| 	var defval = o.defval, raw = o.raw || !Object.prototype.hasOwnProperty.call(o, "raw"); | ||||
| 	var isempty = true, dense = (sheet["!data"] != null); | ||||
| 	var isempty = true; | ||||
| 	var row/*:any*/ = (header === 1) ? [] : {}; | ||||
| 	if(header !== 1) { | ||||
| 		if(Object.defineProperty) try { Object.defineProperty(row, '__rowNum__', {value:R, enumerable:false}); } catch(e) { row.__rowNum__ = R; } | ||||
| 		else row.__rowNum__ = R; | ||||
| 	} | ||||
| 	if(!dense || sheet["!data"][R]) for (var C = r.s.c; C <= r.e.c; ++C) { | ||||
| 		var val = dense ? (sheet["!data"][R]||[])[C] : sheet[cols[C] + rr]; | ||||
| 		if(val == null || val.t === undefined) { | ||||
| 	if(!dense || sheet[R]) for (var C = r.s.c; C <= r.e.c; ++C) { | ||||
| 		var val = dense ? sheet[R][C] : sheet[cols[C] + rr]; | ||||
| 		if(val === undefined || val.t === undefined) { | ||||
| 			if(defval === undefined) continue; | ||||
| 			if(hdr[C] != null) { row[hdr[C]] = defval; } | ||||
| 			continue; | ||||
| @ -24,12 +24,7 @@ function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Ar | ||||
| 		switch(val.t){ | ||||
| 			case 'z': if(v == null) break; continue; | ||||
| 			case 'e': v = (v == 0 ? null : void 0); break; | ||||
| 			case 's': case 'b': | ||||
| 			case 'n': if(!val.z || !fmt_is_date(val.z)) break; | ||||
| 			v = numdate(v); // TODO: date1904 setting should also be stored in worksheet object
 | ||||
| 			if(typeof v == "number") break; | ||||
| 			/* falls through */ | ||||
| 			case 'd': if(!(o && (o.UTC||(o.raw === false)))) v = utc_to_local(new Date(v)); break; | ||||
| 			case 's': case 'd': case 'b': case 'n': break; | ||||
| 			default: throw new Error('unrecognized type ' + val.t); | ||||
| 		} | ||||
| 		if(hdr[C] != null) { | ||||
| @ -39,7 +34,7 @@ function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Ar | ||||
| 				else if(raw && v === null) row[hdr[C]] = null; | ||||
| 				else continue; | ||||
| 			} else { | ||||
| 				row[hdr[C]] = (val.t === 'n' && typeof o.rawNumbers === 'boolean' ? o.rawNumbers : raw) ? v : format_cell(val, v, o); | ||||
| 				row[hdr[C]] = raw && (val.t !== "n" || (val.t === "n" && o.rawNumbers !== false)) ? v : format_cell(val,v,o); | ||||
| 			} | ||||
| 			if(v != null) isempty = false; | ||||
| 		} | ||||
| @ -68,16 +63,16 @@ function sheet_to_json(sheet/*:Worksheet*/, opts/*:?Sheet2JSONOpts*/) { | ||||
| 	var cols/*:Array<string>*/ = []; | ||||
| 	var out/*:Array<any>*/ = []; | ||||
| 	var outi = 0, counter = 0; | ||||
| 	var dense = sheet["!data"] != null; | ||||
| 	var dense = Array.isArray(sheet); | ||||
| 	var R = r.s.r, C = 0; | ||||
| 	var header_cnt = {}; | ||||
| 	if(dense && !sheet["!data"][R]) sheet["!data"][R] = []; | ||||
| 	if(dense && !sheet[R]) sheet[R] = []; | ||||
| 	var colinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!cols"] || []; | ||||
| 	var rowinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!rows"] || []; | ||||
| 	for(C = r.s.c; C <= r.e.c; ++C) { | ||||
| 		if(((colinfo[C]||{}).hidden)) continue; | ||||
| 		cols[C] = encode_col(C); | ||||
| 		val = dense ? sheet["!data"][R][C] : sheet[cols[C] + rr]; | ||||
| 		val = dense ? sheet[R][C] : sheet[cols[C] + rr]; | ||||
| 		switch(header) { | ||||
| 			case 1: hdr[C] = C - r.s.c; break; | ||||
| 			case 2: hdr[C] = cols[C]; break; | ||||
| @ -96,7 +91,7 @@ function sheet_to_json(sheet/*:Worksheet*/, opts/*:?Sheet2JSONOpts*/) { | ||||
| 	} | ||||
| 	for (R = r.s.r + offset; R <= r.e.r; ++R) { | ||||
| 		if ((rowinfo[R]||{}).hidden) continue; | ||||
| 		var row = make_json_row(sheet, r, R, cols, header, hdr, o); | ||||
| 		var row = make_json_row(sheet, r, R, cols, header, hdr, dense, o); | ||||
| 		if((row.isempty === false) || (header === 1 ? o.blankrows !== false : !!o.blankrows)) out[outi++] = row.row; | ||||
| 	} | ||||
| 	out.length = outi; | ||||
| @ -104,20 +99,18 @@ function sheet_to_json(sheet/*:Worksheet*/, opts/*:?Sheet2JSONOpts*/) { | ||||
| } | ||||
| 
 | ||||
| var qreg = /"/g; | ||||
| function make_csv_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Array<string>*/, fs/*:number*/, rs/*:number*/, FS/*:string*/, w/*:number*/, o/*:Sheet2CSVOpts*/)/*:?string*/ { | ||||
| function make_csv_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Array<string>*/, fs/*:number*/, rs/*:number*/, FS/*:string*/, o/*:Sheet2CSVOpts*/)/*:?string*/ { | ||||
| 	var isempty = true; | ||||
| 	var row/*:Array<string>*/ = [], txt = "", rr = encode_row(R); | ||||
| 	var dense = sheet["!data"] != null; | ||||
| 	var datarow = dense && sheet["!data"][R] || []; | ||||
| 	for(var C = r.s.c; C <= r.e.c; ++C) { | ||||
| 		if (!cols[C]) continue; | ||||
| 		var val = dense ? datarow[C]: sheet[cols[C] + rr]; | ||||
| 		var val = o.dense ? (sheet[R]||[])[C]: sheet[cols[C] + rr]; | ||||
| 		if(val == null) txt = ""; | ||||
| 		else if(val.v != null) { | ||||
| 			isempty = false; | ||||
| 			txt = ''+(o.rawNumbers && val.t == "n" ? val.v : format_cell(val, null, o)); | ||||
| 			for(var i = 0, cc = 0; i !== txt.length; ++i) if((cc = txt.charCodeAt(i)) === fs || cc === rs || cc === 34 || o.forceQuotes) {txt = "\"" + txt.replace(qreg, '""') + "\""; break; } | ||||
| 			if(txt == "ID" && w == 0 && row.length == 0) txt = '"ID"'; | ||||
| 			if(txt == "ID") txt = '"ID"'; | ||||
| 		} else if(val.f != null && !val.F) { | ||||
| 			isempty = false; | ||||
| 			txt = '=' + val.f; if(txt.indexOf(",") >= 0) txt = '"' + txt.replace(qreg, '""') + '"'; | ||||
| @ -125,7 +118,6 @@ function make_csv_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Arr | ||||
| 		/* NOTE: Excel CSV does not support array formulae */ | ||||
| 		row.push(txt); | ||||
| 	} | ||||
| 	if(o.strip) while(row[row.length - 1] === "") --row.length; | ||||
| 	if(o.blankrows === false && isempty) return null; | ||||
| 	return row.join(FS); | ||||
| } | ||||
| @ -137,17 +129,21 @@ function sheet_to_csv(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/)/*:string*/ { | ||||
| 	var r = safe_decode_range(sheet["!ref"]); | ||||
| 	var FS = o.FS !== undefined ? o.FS : ",", fs = FS.charCodeAt(0); | ||||
| 	var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0); | ||||
| 	var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$"); | ||||
| 	var row = "", cols/*:Array<string>*/ = []; | ||||
| 	o.dense = Array.isArray(sheet); | ||||
| 	var colinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!cols"] || []; | ||||
| 	var rowinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!rows"] || []; | ||||
| 	for(var C = r.s.c; C <= r.e.c; ++C) if (!((colinfo[C]||{}).hidden)) cols[C] = encode_col(C); | ||||
| 	var w = 0; | ||||
| 	for(var R = r.s.r; R <= r.e.r; ++R) { | ||||
| 		if ((rowinfo[R]||{}).hidden) continue; | ||||
| 		row = make_csv_row(sheet, r, R, cols, fs, rs, FS, w, o); | ||||
| 		row = make_csv_row(sheet, r, R, cols, fs, rs, FS, o); | ||||
| 		if(row == null) { continue; } | ||||
| 		if(o.strip) row = row.replace(endregex,""); | ||||
| 		if(row || (o.blankrows !== false)) out.push((w++ ? RS : "") + row); | ||||
| 	} | ||||
| 	delete o.dense; | ||||
| 	return out.join(""); | ||||
| } | ||||
| 
 | ||||
| @ -159,18 +155,18 @@ function sheet_to_txt(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) { | ||||
| 	return String.fromCharCode(255) + String.fromCharCode(254) + o; | ||||
| } | ||||
| 
 | ||||
| function sheet_to_formulae(sheet/*:Worksheet*/, opts/*:?Sheet2FormulaOpts*/)/*:Array<string>*/ { | ||||
| function sheet_to_formulae(sheet/*:Worksheet*/)/*:Array<string>*/ { | ||||
| 	var y = "", x, val=""; | ||||
| 	if(sheet == null || sheet["!ref"] == null) return []; | ||||
| 	var r = safe_decode_range(sheet['!ref']), rr = "", cols/*:Array<string>*/ = [], C; | ||||
| 	var cmds/*:Array<string>*/ = []; | ||||
| 	var dense = sheet["!data"] != null; | ||||
| 	var dense = Array.isArray(sheet); | ||||
| 	for(C = r.s.c; C <= r.e.c; ++C) cols[C] = encode_col(C); | ||||
| 	for(var R = r.s.r; R <= r.e.r; ++R) { | ||||
| 		rr = encode_row(R); | ||||
| 		for(C = r.s.c; C <= r.e.c; ++C) { | ||||
| 			y = cols[C] + rr; | ||||
| 			x = dense ? (sheet["!data"][R]||[])[C] : sheet[y]; | ||||
| 			x = dense ? (sheet[R]||[])[C] : sheet[y]; | ||||
| 			val = ""; | ||||
| 			if(x === undefined) continue; | ||||
| 			else if(x.F != null) { | ||||
| @ -180,7 +176,6 @@ function sheet_to_formulae(sheet/*:Worksheet*/, opts/*:?Sheet2FormulaOpts*/)/*:A | ||||
| 				if(y.indexOf(":") == -1) y = y + ":" + y; | ||||
| 			} | ||||
| 			if(x.f != null) val = x.f; | ||||
| 			else if(opts && opts.values === false) continue; | ||||
| 			else if(x.t == 'z') continue; | ||||
| 			else if(x.t == 'n' && x.v != null) val = "" + x.v; | ||||
| 			else if(x.t == 'b') val = x.v ? "TRUE" : "FALSE"; | ||||
| @ -196,11 +191,10 @@ function sheet_to_formulae(sheet/*:Worksheet*/, opts/*:?Sheet2FormulaOpts*/)/*:A | ||||
| 
 | ||||
| function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet*/ { | ||||
| 	var o = opts || {}; | ||||
| 	var dense = _ws ? (_ws["!data"] != null) : o.dense; | ||||
| 	var dense = _ws ? Array.isArray(_ws) : o.dense; | ||||
| 	if(DENSE != null && dense == null) dense = DENSE; | ||||
| 	var offset = +!o.skipHeader; | ||||
| 	var ws/*:Worksheet*/ = _ws || ({}); | ||||
| 	if(!_ws && dense) ws["!data"] = []; | ||||
| 	var ws/*:Worksheet*/ = _ws || (dense ? ([]/*:any*/) : ({}/*:any*/)); | ||||
| 	var _R = 0, _C = 0; | ||||
| 	if(ws && o.origin != null) { | ||||
| 		if(typeof o.origin == 'number') _R = o.origin; | ||||
| @ -219,27 +213,25 @@ function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet | ||||
| 		if(_R == -1) { _R = 0; range.e.r = js.length - 1 + offset; } | ||||
| 	} | ||||
| 	var hdr/*:Array<string>*/ = o.header || [], C = 0; | ||||
| 	var ROW = []; | ||||
| 
 | ||||
| 	js.forEach(function (JS, R/*:number*/) { | ||||
| 		if(dense && !ws["!data"][_R + R + offset]) ws["!data"][_R + R + offset] = []; | ||||
| 		if(dense) ROW = ws["!data"][_R + R + offset]; | ||||
| 		if(!ws[_R + R + offset]) ws[_R + R + offset] = []; | ||||
| 		var ROW = ws[_R + R + offset]; | ||||
| 		keys(JS).forEach(function(k) { | ||||
| 			if((C=hdr.indexOf(k)) == -1) hdr[C=hdr.length] = k; | ||||
| 			var v = JS[k]; | ||||
| 			var t = 'z'; | ||||
| 			var z = ""; | ||||
| 			var ref = dense ? "" : (encode_col(_C + C) + encode_row(_R + R + offset)); | ||||
| 			var ref = dense ? "" : encode_cell({c:_C + C,r:_R + R + offset}); | ||||
| 			var cell/*:Cell*/ = dense ? ROW[_C + C] : ws[ref]; | ||||
| 			if(v && typeof v === 'object' && !(v instanceof Date)){ | ||||
| 				if(dense) ROW[_C + C] = v; | ||||
| 				else ws[ref] = v; | ||||
| 				ws[ref] = v; | ||||
| 			} else { | ||||
| 				if(typeof v == 'number') t = 'n'; | ||||
| 				else if(typeof v == 'boolean') t = 'b'; | ||||
| 				else if(typeof v == 'string') t = 's'; | ||||
| 				else if(v instanceof Date) { | ||||
| 					t = 'd'; | ||||
| 					if(!o.UTC) v = local_to_utc(v); | ||||
| 					if(!o.cellDates) { t = 'n'; v = datenum(v); } | ||||
| 					z = (cell != null && cell.z && fmt_is_date(cell.z)) ? cell.z : (o.dateNF || table_fmt[14]); | ||||
| 				} | ||||
| @ -247,7 +239,8 @@ function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet | ||||
| 				if(!cell) { | ||||
| 					if(!dense) ws[ref] = cell = ({t:t, v:v}/*:any*/); | ||||
| 					else ROW[_C + C] = cell = ({t:t, v:v}/*:any*/); | ||||
| 				} else { | ||||
| 				} | ||||
| 				else { | ||||
| 					cell.t = t; cell.v = v; | ||||
| 					delete cell.w; delete cell.R; | ||||
| 					if(z) cell.z = z; | ||||
| @ -258,9 +251,9 @@ function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet | ||||
| 	}); | ||||
| 	range.e.c = Math.max(range.e.c, _C + hdr.length - 1); | ||||
| 	var __R = encode_row(_R); | ||||
| 	if(dense && !ws["!data"][_R]) ws["!data"][_R] = []; | ||||
| 	if(dense && !ws[_R]) ws[_R] = []; | ||||
| 	if(offset) for(C = 0; C < hdr.length; ++C) { | ||||
| 		if(dense) ws["!data"][_R][C + _C] = {t:'s', v:hdr[C]}; | ||||
| 		if(dense) ws[_R][C + _C] = {t:'s', v:hdr[C]}; | ||||
| 		else ws[encode_col(C + _C) + __R] = {t:'s', v:hdr[C]}; | ||||
| 	} | ||||
| 	ws['!ref'] = encode_range(range); | ||||
| @ -272,17 +265,18 @@ function json_to_sheet(js/*:Array<any>*/, opts)/*:Worksheet*/ { return sheet_add | ||||
| function ws_get_cell_stub(ws/*:Worksheet*/, R, C/*:?number*/)/*:Cell*/ { | ||||
| 	/* A1 cell address */ | ||||
| 	if(typeof R == "string") { | ||||
| 		if(ws["!data"] != null) { | ||||
| 		/* dense */ | ||||
| 		if(Array.isArray(ws)) { | ||||
| 			var RC = decode_cell(R); | ||||
| 			if(!ws["!data"][RC.r]) ws["!data"][RC.r] = []; | ||||
| 			return ws["!data"][RC.r][RC.c] || (ws["!data"][RC.r][RC.c] = {t:'z'}); | ||||
| 			if(!ws[RC.r]) ws[RC.r] = []; | ||||
| 			return ws[RC.r][RC.c] || (ws[RC.r][RC.c] = {t:'z'}); | ||||
| 		} | ||||
| 		return ws[R] || (ws[R] = {t:'z'}); | ||||
| 	} | ||||
| 	/* cell address object */ | ||||
| 	if(typeof R != "number") return ws_get_cell_stub(ws, encode_cell(R)); | ||||
| 	/* R and C are 0-based indices */ | ||||
| 	return ws_get_cell_stub(ws, encode_col(C||0) + encode_row(R)); | ||||
| 	return ws_get_cell_stub(ws, encode_cell({r:R,c:C||0})); | ||||
| } | ||||
| 
 | ||||
| /* find sheet index for given name / validate index */ | ||||
| @ -297,11 +291,9 @@ function wb_sheet_idx(wb/*:Workbook*/, sh/*:number|string*/) { | ||||
| 	} else throw new Error("Cannot find sheet |" + sh + "|"); | ||||
| } | ||||
| 
 | ||||
| /* simple blank or single-sheet workbook object */ | ||||
| function book_new(ws/*:?Worksheet*/, wsname/*:?string*/)/*:Workbook*/ { | ||||
| 	var wb = { SheetNames: [], Sheets: {} }; | ||||
| 	if(ws) book_append_sheet(wb, ws, wsname || "Sheet1"); | ||||
| 	return wb; | ||||
| /* simple blank workbook object */ | ||||
| function book_new()/*:Workbook*/ { | ||||
| 	return { SheetNames: [], Sheets: {} }; | ||||
| } | ||||
| 
 | ||||
| /* add a worksheet to the end of a given workbook */ | ||||
| @ -309,10 +301,10 @@ function book_append_sheet(wb/*:Workbook*/, ws/*:Worksheet*/, name/*:?string*/, | ||||
| 	var i = 1; | ||||
| 	if(!name) for(; i <= 0xFFFF; ++i, name = undefined) if(wb.SheetNames.indexOf(name = "Sheet" + i) == -1) break; | ||||
| 	if(!name || wb.SheetNames.length >= 0xFFFF) throw new Error("Too many worksheets"); | ||||
| 	if(roll && wb.SheetNames.indexOf(name) >= 0 && name.length < 32) { | ||||
| 		var m = name.match(/\d+$/); // at this point, name length is capped at 32
 | ||||
| 		i = m && +m[0] || 0; | ||||
| 		var root = m && name.slice(0, m.index) || name; | ||||
| 	if(roll && wb.SheetNames.indexOf(name) >= 0) { | ||||
| 		var m = name.match(/(^.*?)(\d+)$/); | ||||
| 		i = m && +m[2] || 0; | ||||
| 		var root = m && m[1] || name; | ||||
| 		for(++i; i <= 0xFFFF; ++i) if(wb.SheetNames.indexOf(name = root + i) == -1) break; | ||||
| 	} | ||||
| 	check_ws_name(name); | ||||
|  | ||||
| @ -9,7 +9,6 @@ var utils/*:any*/ = { | ||||
| 	decode_cell: decode_cell, | ||||
| 	decode_range: decode_range, | ||||
| 	format_cell: format_cell, | ||||
| 	sheet_new: sheet_new, | ||||
| 	sheet_add_aoa: sheet_add_aoa, | ||||
| 	sheet_add_json: sheet_add_json, | ||||
| 	sheet_add_dom: sheet_add_dom, | ||||
|  | ||||
							
								
								
									
										174
									
								
								bits/97_node.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										174
									
								
								bits/97_node.js
									
									
									
									
									
								
							| @ -8,7 +8,9 @@ function write_csv_stream(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) { | ||||
| 	var r = safe_decode_range(sheet["!ref"]); | ||||
| 	var FS = o.FS !== undefined ? o.FS : ",", fs = FS.charCodeAt(0); | ||||
| 	var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0); | ||||
| 	var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$"); | ||||
| 	var row/*:?string*/ = "", cols/*:Array<string>*/ = []; | ||||
| 	o.dense = Array.isArray(sheet); | ||||
| 	var colinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!cols"] || []; | ||||
| 	var rowinfo/*:Array<RowInfo>*/ = o.skipHidden && sheet["!rows"] || []; | ||||
| 	for(var C = r.s.c; C <= r.e.c; ++C) if (!((colinfo[C]||{}).hidden)) cols[C] = encode_col(C); | ||||
| @ -19,8 +21,9 @@ function write_csv_stream(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) { | ||||
| 		while(R <= r.e.r) { | ||||
| 			++R; | ||||
| 			if ((rowinfo[R-1]||{}).hidden) continue; | ||||
| 			row = make_csv_row(sheet, r, R-1, cols, fs, rs, FS, w, o); | ||||
| 			row = make_csv_row(sheet, r, R-1, cols, fs, rs, FS, o); | ||||
| 			if(row != null) { | ||||
| 				if(o.strip) row = row.replace(endregex,""); | ||||
| 				if(row || (o.blankrows !== false)) return stream.push((w++ ? RS : "") + row); | ||||
| 			} | ||||
| 		} | ||||
| @ -37,6 +40,7 @@ function write_html_stream(ws/*:Worksheet*/, opts/*:?Sheet2HTMLOpts*/) { | ||||
| 	var footer = o.footer != null ? o.footer : HTML_END; | ||||
| 	stream.push(header); | ||||
| 	var r = decode_range(ws['!ref']); | ||||
| 	o.dense = Array.isArray(ws); | ||||
| 	stream.push(make_html_preamble(ws, r, o)); | ||||
| 	var R = r.s.r; | ||||
| 	var end = false; | ||||
| @ -74,16 +78,16 @@ function write_json_stream(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) { | ||||
| 	var rr = encode_row(r.s.r); | ||||
| 	var cols/*:Array<string>*/ = []; | ||||
| 	var counter = 0; | ||||
| 	var dense = sheet["!data"] != null; | ||||
| 	var dense = Array.isArray(sheet); | ||||
| 	var R = r.s.r, C = 0; | ||||
| 	var header_cnt = {}; | ||||
| 	if(dense && !sheet["!data"][R]) sheet["!data"][R] = []; | ||||
| 	if(dense && !sheet[R]) sheet[R] = []; | ||||
| 	var colinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!cols"] || []; | ||||
| 	var rowinfo/*:Array<RowInfo>*/ = o.skipHidden && sheet["!rows"] || []; | ||||
| 	for(C = r.s.c; C <= r.e.c; ++C) { | ||||
| 		if(((colinfo[C]||{}).hidden)) continue; | ||||
| 		cols[C] = encode_col(C); | ||||
| 		val = dense ? sheet["!data"][R][C] : sheet[cols[C] + rr]; | ||||
| 		val = dense ? sheet[R][C] : sheet[cols[C] + rr]; | ||||
| 		switch(header) { | ||||
| 			case 1: hdr[C] = C - r.s.c; break; | ||||
| 			case 2: hdr[C] = cols[C]; break; | ||||
| @ -103,11 +107,8 @@ function write_json_stream(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) { | ||||
| 	R = r.s.r + offset; | ||||
| 	stream._read = function() { | ||||
| 		while(R <= r.e.r) { | ||||
| 			if ((rowinfo[R]||{}).hidden) { | ||||
| 				++R; | ||||
| 				continue; | ||||
| 			}; | ||||
| 			var row = make_json_row(sheet, r, R, cols, header, hdr, o); | ||||
| 			if ((rowinfo[R-1]||{}).hidden) continue; | ||||
| 			var row = make_json_row(sheet, r, R, cols, header, hdr, dense, o); | ||||
| 			++R; | ||||
| 			if((row.isempty === false) || (header === 1 ? o.blankrows !== false : !!o.blankrows)) { | ||||
| 				stream.push(row.row); | ||||
| @ -119,164 +120,9 @@ function write_json_stream(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) { | ||||
| 	return stream; | ||||
| } | ||||
| 
 | ||||
| function write_xlml_stream(wb/*:Workbook*/, o/*:?Sheet2XLMLOpts*/) { | ||||
| 	var stream = _Readable(); | ||||
| 	var opts = o == null ? {} : o; | ||||
| 	var stride = +opts.stride || 10; | ||||
| 	if(!wb.SSF) wb.SSF = dup(table_fmt); | ||||
| 	if(wb.SSF) { | ||||
| 		make_ssf(); SSF_load_table(wb.SSF); | ||||
| 		// $FlowIgnore
 | ||||
| 		opts.revssf = evert_num(wb.SSF); opts.revssf[wb.SSF[65535]] = 0; | ||||
| 		opts.ssf = wb.SSF; | ||||
| 		opts.cellXfs = []; | ||||
| 		get_cell_style(opts.cellXfs, {}, {revssf:{"General":0}}); | ||||
| 	} | ||||
| 
 | ||||
| 	/* do one pass to determine styles since they must be added before tables */ | ||||
| 	wb.SheetNames.forEach(function(n) { | ||||
| 		var ws = wb.Sheets[n]; | ||||
| 		if(!ws || !ws["!ref"]) return; | ||||
| 		var range = decode_range(ws["!ref"]); | ||||
| 		var dense = ws["!data"] != null; | ||||
| 		var ddata = dense ? ws["!data"] : []; | ||||
| 		var addr = {r:0,c:0}; | ||||
| 		for(var R = range.s.r; R <= range.e.r; ++R) { | ||||
| 			addr.r = R; | ||||
| 			if(dense && !ddata[R]) continue; | ||||
| 			for(var C = range.s.c; C <= range.e.c; ++C) { | ||||
| 				addr.c = C; | ||||
| 				var cell = dense ? ddata[R][C] : ws[encode_col(C) + encode_row(R)]; | ||||
| 				if(!cell) continue; | ||||
| 				if(cell.t == "d" && cell.z == null) { cell = dup(cell); cell.z = table_fmt[14]; } | ||||
| 				void get_cell_style(opts.cellXfs, cell, opts); | ||||
| 			} | ||||
| 		} | ||||
| 	}); | ||||
| 	var sty = write_sty_xlml(wb, opts); | ||||
| 
 | ||||
| 	var stage = 0, wsidx = 0, ws = wb.Sheets[wb.SheetNames[wsidx]], range = safe_decode_range(ws), R = -1, T = false; | ||||
| 
 | ||||
| 	var marr = [], mi = 0, dense = false, darr = [], addr = {r:0,c:0}; | ||||
| 
 | ||||
| 	stream._read = function() { switch(stage) { | ||||
| 		/* header */ | ||||
| 		case 0: { | ||||
| 			stage = 1; | ||||
| 			stream.push(XML_HEADER); | ||||
| 			stream.push("<Workbook" + wxt_helper({ | ||||
| 				'xmlns':      XLMLNS.ss, | ||||
| 				'xmlns:o':    XLMLNS.o, | ||||
| 				'xmlns:x':    XLMLNS.x, | ||||
| 				'xmlns:ss':   XLMLNS.ss, | ||||
| 				'xmlns:dt':   XLMLNS.dt, | ||||
| 				'xmlns:html': XLMLNS.html | ||||
| 			}) + ">"); | ||||
| 		} break; | ||||
| 
 | ||||
| 		/* preamble */ | ||||
| 		case 1: { | ||||
| 			stage = 2; | ||||
| 			stream.push(write_props_xlml(wb, opts)); | ||||
| 			stream.push(write_wb_xlml(wb, opts)); | ||||
| 		} break; | ||||
| 
 | ||||
| 		/* style and name tables */ | ||||
| 		case 2: { | ||||
| 			stage = 3; | ||||
| 			stream.push(sty); | ||||
| 			stream.push(write_names_xlml(wb, opts)); | ||||
| 		} break; | ||||
| 
 | ||||
| 		/* worksheet preamble */ | ||||
| 		case 3: { | ||||
| 			T = false; | ||||
| 			if(wsidx >= wb.SheetNames.length) { stage = -1; stream.push(""); break; } | ||||
| 
 | ||||
| 			stream.push("<Worksheet" + wxt_helper({ "ss:Name": escapexml(wb.SheetNames[wsidx])}) + ">"); | ||||
| 
 | ||||
| 			ws = wb.Sheets[wb.SheetNames[wsidx]]; | ||||
| 			if(!ws) { stream.push("</Worksheet>"); return void ++wsidx; } | ||||
| 
 | ||||
| 			var names = write_ws_xlml_names(ws, opts, wsidx, wb); | ||||
| 			if(names.length) stream.push("<Names>" + names + "</Names>"); | ||||
| 
 | ||||
| 			if(!ws["!ref"]) return (stage = 5); | ||||
| 			range = safe_decode_range(ws["!ref"]); | ||||
| 			R = range.s.r; | ||||
| 			stage = 4; | ||||
| 		} break; | ||||
| 
 | ||||
| 		/* worksheet intramble */ | ||||
| 		case 4: { | ||||
| 			if(R < 0 || R > range.e.r) { if(T) stream.push("</Table>"); return void (stage = 5); } | ||||
| 
 | ||||
| 			if(R <= range.s.r) { | ||||
| 				if(ws['!cols']) ws['!cols'].forEach(function(n, i) { | ||||
| 					process_col(n); | ||||
| 					var w = !!n.width; | ||||
| 					var p = col_obj_w(i, n); | ||||
| 					var k/*:any*/ = {"ss:Index":i+1}; | ||||
| 					if(w) k['ss:Width'] = width2px(p.width); | ||||
| 					if(n.hidden) k['ss:Hidden']="1"; | ||||
| 					if(!T) { T = true; stream.push("<Table>"); } | ||||
| 					stream.push(writextag("Column",null,k)); | ||||
| 				}); | ||||
| 				dense = ws["!data"] != null; | ||||
| 				if(dense) darr = ws["!data"]; | ||||
| 				addr.r = addr.c = 0; | ||||
| 			} | ||||
| 
 | ||||
| 			/* process `stride` rows per invocation */ | ||||
| 			for(var cnt = 0; R <= range.e.r && cnt < stride; ++R, ++cnt) { | ||||
| 				var row = [write_ws_xlml_row(R, (ws['!rows']||[])[R])]; | ||||
| 				addr.r = R; | ||||
| 				if(!(dense && !darr[R])) for(var C = range.s.c; C <= range.e.c; ++C) { | ||||
| 					addr.c = C; | ||||
| 					var skip = false; | ||||
| 					for(mi = 0; mi != marr.length; ++mi) { | ||||
| 						if(marr[mi].s.c > C) continue; | ||||
| 						if(marr[mi].s.r > R) continue; | ||||
| 						if(marr[mi].e.c < C) continue; | ||||
| 						if(marr[mi].e.r < R) continue; | ||||
| 						if(marr[mi].s.c != C || marr[mi].s.r != R) skip = true; | ||||
| 						break; | ||||
| 					} | ||||
| 					if(skip) continue; | ||||
| 					var ref = encode_col(C) + encode_row(R), cell = dense ? darr[R][C] : ws[ref]; | ||||
| 					row.push(write_ws_xlml_cell(cell, ref, ws, opts, wsidx, wb, addr)); | ||||
| 				} | ||||
| 				row.push("</Row>"); | ||||
| 				if(!T) { T = true; stream.push("<Table>"); } | ||||
| 				stream.push(row.join("")); | ||||
| 			} | ||||
| 		} break; | ||||
| 
 | ||||
| 		/* worksheet postamble */ | ||||
| 		case 5: { | ||||
| 			stream.push(write_ws_xlml_wsopts(ws, opts, wsidx, wb)); | ||||
| 			if(ws && ws["!autofilter"]) stream.push('<AutoFilter x:Range="' + a1_to_rc(fix_range(ws["!autofilter"].ref), {r:0,c:0}) + '" xmlns="urn:schemas-microsoft-com:office:excel"></AutoFilter>'); | ||||
| 			stream.push("</Worksheet>"); | ||||
| 			wsidx++; R = -1; | ||||
| 			return void (stage = 3); | ||||
| 		} | ||||
| 
 | ||||
| 		/* footer */ | ||||
| 		case -1: { | ||||
| 			stage = -2; | ||||
| 			stream.push("</Workbook>"); | ||||
| 		} break; | ||||
| 
 | ||||
| 		/* exeunt */ | ||||
| 		case -2: stream.push(null); break; | ||||
| 	}}; | ||||
| 	return stream; | ||||
| } | ||||
| 
 | ||||
| var __stream = { | ||||
| 	to_json: write_json_stream, | ||||
| 	to_html: write_html_stream, | ||||
| 	to_csv: write_csv_stream, | ||||
| 	to_xlml: write_xlml_stream, | ||||
| 	set_readable: set_readable | ||||
| }; | ||||
|  | ||||
| @ -10,8 +10,6 @@ XLSX.writeFileAsync = writeFileAsync; | ||||
| XLSX.utils = utils; | ||||
| XLSX.writeXLSX = writeSyncXLSX; | ||||
| XLSX.writeFileXLSX = writeFileSyncXLSX; | ||||
| XLSX.set_fs = set_fs; | ||||
| XLSX.set_cptable = set_cptable; | ||||
| XLSX.SSF = SSF; | ||||
| if(typeof __stream !== "undefined") XLSX.stream = __stream; | ||||
| if(typeof CFB !== "undefined") XLSX.CFB = CFB; | ||||
|  | ||||
							
								
								
									
										76
									
								
								demos/README.md
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										76
									
								
								demos/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,76 @@ | ||||
| # Demos | ||||
| 
 | ||||
| These demos are intended to demonstrate how to load this library in various | ||||
| ecosystems.  The library is designed to be used in the web browser and in node | ||||
| contexts, using dynamic feature tests to pull in features when necessary.  This | ||||
| works extremely well in common use cases: script tag insertion and node require. | ||||
| 
 | ||||
| Systems like webpack try to be clever by performing simple static analysis to | ||||
| pull in code.  However, they do not support dynamic type tests, breaking | ||||
| compatibility with traditional scripts.  Configuration is required.  The demos | ||||
| cover basic configuration steps for various systems and should "just work". | ||||
| 
 | ||||
| Mobile app and other larger demos do not include the full build structure. The | ||||
| demos have `Makefile` scripts that show how to reproduce the full projects.  The | ||||
| scripts have been tested against iOS and OSX.  For Windows platforms, GNU make | ||||
| can be installed with Bash on Windows or with `cygwin`. | ||||
| 
 | ||||
| ### Included Demos | ||||
| 
 | ||||
| **JavaScript APIs** | ||||
| - [`XMLHttpRequest and fetch`](https://docs.sheetjs.com/docs/getting-started/demos/network) | ||||
| - [`Clipboard Data`](https://docs.sheetjs.com/docs/getting-started/demos/clipboard) | ||||
| - [`Typed Arrays for Machine Learning`](https://docs.sheetjs.com/docs/getting-started/demos/ml) | ||||
| - [`LocalStorage and SessionStorage`](https://docs.sheetjs.com/docs/getting-started/demos/database#localstorage-and-sessionstorage) | ||||
| - [`Web SQL Database`](https://docs.sheetjs.com/docs/getting-started/demos/database#websql) | ||||
| - [`IndexedDB`](https://docs.sheetjs.com/docs/getting-started/demos/database#indexeddb) | ||||
| 
 | ||||
| **Frameworks** | ||||
| - [`Angular.JS`](https://docs.sheetjs.com/docs/getting-started/demos/legacy#angularjs) | ||||
| - [`Angular 2+ and Ionic`](angular2/) | ||||
| - [`Knockout`](https://docs.sheetjs.com/docs/getting-started/demos/legacy#knockoutjs) | ||||
| - [`React, React Native and NextJS`](react/) | ||||
| - [`VueJS, WeeX and NuxtJS`](vue/) | ||||
| 
 | ||||
| **Front-End UI Components** | ||||
| - [`canvas-datagrid`](https://docs.sheetjs.com/docs/getting-started/demos/grid#canvas-datagrid) | ||||
| - [`x-spreadsheet`](xspreadsheet/) | ||||
| - [`react-data-grid`](react/modify/) | ||||
| - [`vue3-table-light`](vue/modify/) | ||||
| - [`angular-ui-grid`](https://docs.sheetjs.com/docs/getting-started/demos/grid#angular-ui-grid) | ||||
| 
 | ||||
| **Platforms and Integrations** | ||||
| - [`Command-Line Tools`](https://docs.sheetjs.com/docs/getting-started/demos/cli) | ||||
| - [`NodeJS Server-Side Processing`](server/) | ||||
| - [`Electron`](https://docs.sheetjs.com/docs/getting-started/demos/desktop#electron) | ||||
| - [`NW.js`](https://docs.sheetjs.com/docs/getting-started/demos/desktop#nwjs) | ||||
| - [`Chrome / Chromium Extension`](https://docs.sheetjs.com/docs/getting-started/demos/chromium) | ||||
| - [`Google Sheets API`](https://docs.sheetjs.com/docs/getting-started/demos/gsheet) | ||||
| - [`ExtendScript for Adobe Apps`](https://docs.sheetjs.com/docs/getting-started/demos/extendscript) | ||||
| - [`NetSuite SuiteScript`](https://docs.sheetjs.com/docs/getting-started/demos/netsuite) | ||||
| - [`SalesForce Lightning Web Components`](https://docs.sheetjs.com/docs/getting-started/demos/salesforce) | ||||
| - [`Excel JavaScript API`](https://docs.sheetjs.com/docs/getting-started/demos/excel) | ||||
| - [`Headless Automation`](https://docs.sheetjs.com/docs/getting-started/demos/headless) | ||||
| - [`Swift JSC and Other JavaScript Engines`](altjs/) | ||||
| - [`"serverless" functions`](function/) | ||||
| - [`Databases and Structured Data Stores`](https://docs.sheetjs.com/docs/getting-started/demos/database) | ||||
| - [`NoSQL, K/V, and Unstructured Data Stores`](https://docs.sheetjs.com/docs/getting-started/demos/nosql) | ||||
| - [`Legacy Internet Explorer`](oldie/) | ||||
| 
 | ||||
| **Bundlers and Tooling** | ||||
| - [`browserify`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#browserify) | ||||
| - [`bun`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#bun) | ||||
| - [`esbuild`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#esbuild) | ||||
| - [`parcel`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#parcel) | ||||
| - [`requirejs`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#requirejs) | ||||
| - [`rollup`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#rollup) | ||||
| - [`snowpack`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#snowpack) | ||||
| - [`swc`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#swc) | ||||
| - [`systemjs`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#systemjs) | ||||
| - [`vite`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#vite) | ||||
| - [`webpack 2.x`](webpack/) | ||||
| - [`wmr`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#wmr) | ||||
| 
 | ||||
| Other examples are included in the [showcase](demos/showcase/). | ||||
| 
 | ||||
| [](https://github.com/SheetJS/js-xlsx) | ||||
							
								
								
									
										10
									
								
								demos/altjs/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										10
									
								
								demos/altjs/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| sheetjs.* | ||||
| SheetJSSwift | ||||
| duk* | ||||
| *.class | ||||
| *.jar | ||||
| rhino | ||||
| shim.min.js | ||||
| xlsx.*.js | ||||
| payload.js | ||||
| goja | ||||
							
								
								
									
										3
									
								
								demos/altjs/.swiftlint.yml
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										3
									
								
								demos/altjs/.swiftlint.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| disabled_rules: | ||||
|   - trailing_semicolon | ||||
|   - identifier_name | ||||
							
								
								
									
										60
									
								
								demos/altjs/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										60
									
								
								demos/altjs/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,60 @@ | ||||
| .PHONY: all | ||||
| all: duktape nashorn rhinojs swift goja | ||||
| 
 | ||||
| .PHONY: base | ||||
| base: | ||||
| 	if [ ! -e sheetjs.xlsx ]; then node ../../tests/write.js; fi | ||||
| 	if [ ! -e xlsx.full.min.js ]; then cp ../../dist/xlsx.full.min.js .; fi | ||||
| 	if [ ! -e shim.min.js ]; then cp ../../dist/shim.min.js .; fi | ||||
| 
 | ||||
| .PHONY: duk | ||||
| duk: base | ||||
| 	bash ./duktape.sh | ||||
| 	gcc -std=c99 -Wall -osheetjs.duk sheetjs.duk.c duktape.c -lm | ||||
| 
 | ||||
| .PHONY: duktape | ||||
| duktape: duk ## duktape demo
 | ||||
| 	for ext in xlsx xlsb biff8.xls xml.xls; do ./sheetjs.duk sheetjs.$$ext; done | ||||
| 
 | ||||
| .PHONY: nashorn | ||||
| nashorn: base ## nashorn demo
 | ||||
| 	jjs nashorn.js | ||||
| 
 | ||||
| .PHONY: swift | ||||
| swift: base ## swift demo
 | ||||
| 	swiftc SheetJSCore.swift main.swift -o SheetJSSwift | ||||
| 	./SheetJSSwift | ||||
| 
 | ||||
| .PHONY: goja | ||||
| goja: base ## goja demo
 | ||||
| 	go build goja.go | ||||
| 	for ext in xlsx xlsb biff8.xls xml.xls; do ./goja sheetjs.$$ext; done | ||||
| 
 | ||||
| .PHONY: chakra | ||||
| chakra: base ## Chakra demo
 | ||||
| 	node -pe "fs.writeFileSync('payload.js', 'var payload = \"' + fs.readFileSync('sheetjs.xlsx').toString('base64') + '\";')" | ||||
| 	cat global.js xlsx.full.min.js payload.js chakra.js > xlsx.chakra.js | ||||
| 	chakra ./xlsx.chakra.js | ||||
| 
 | ||||
| .PHONY: rhinojs ## rhino demo
 | ||||
| rhinojs: base SheetJSRhino.class | ||||
| 	for ext in xlsx xlsb biff8.xls xml.xls; do java -cp .:SheetJS.jar:rhino.jar SheetJSRhino sheetjs.$$ext; done | ||||
| 
 | ||||
| RHDEPS=$(filter-out SheetJSRhino.class,$(patsubst %.java,%.class,$(wildcard com/sheetjs/*.java))) | ||||
| $(RHDEPS): %.class: %.java rhino.jar | ||||
| 	javac -cp .:SheetJS.jar:rhino.jar $*.java | ||||
| 
 | ||||
| SheetJSRhino.class: $(RHDEPS) | ||||
| 	jar -cf SheetJS.jar $^ xlsx.full.min.js | ||||
| 	javac -cp .:SheetJS.jar:rhino.jar SheetJSRhino.java | ||||
| 
 | ||||
| rhino.jar: | ||||
| 	if [ ! -e rhino ]; then git clone --depth=1 https://github.com/mozilla/rhino; fi | ||||
| 	#if [ ! -e rhino/build/rhino*/js.jar ]; then cd rhino; ant jar; fi | ||||
| 	#cp rhino/build/rhino*/js.jar rhino.jar | ||||
| 	if [ ! -e rhino/buildGradle/libs/rhino-[0-1]*.jar ]; then cd rhino; ./gradlew jar; fi | ||||
| 	cp rhino/buildGradle/libs/rhino-[0-9]*.jar rhino.jar | ||||
| 
 | ||||
| .PHONY: clean | ||||
| clean: | ||||
| 	rm SheetJS.jar *.class com/sheetjs/*.class | ||||
							
								
								
									
										186
									
								
								demos/altjs/README.md
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										186
									
								
								demos/altjs/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,186 @@ | ||||
| # Other JS Engines and Deployments | ||||
| 
 | ||||
| There are many JS engines and deployments outside of web browsers. NodeJS is the | ||||
| most popular deployment, but there are many others for special use cases.  Some | ||||
| optimize for low overhead and others optimize for ease of embedding within other | ||||
| applications.  Since it was designed for ES3 engines, the library can be used in | ||||
| those settings!  This demo tries to demonstrate a few alternative deployments. | ||||
| 
 | ||||
| Some engines provide no default global object.  To create a global reference: | ||||
| 
 | ||||
| ```js | ||||
| var global = (function(){ return this; }).call(null); | ||||
| ``` | ||||
| 
 | ||||
| 
 | ||||
| ## Swift + JavaScriptCore | ||||
| 
 | ||||
| iOS and OSX ship with the JavaScriptCore framework for running JS scripts from | ||||
| Swift and Objective-C.  Hybrid function invocation is tricky, but explicit data | ||||
| passing is straightforward.  The demo shows a standalone example for OSX.  For | ||||
| playgrounds, the library should be copied to shared playground data directory | ||||
| (usually `~/Documents/Shared Playground Data`): | ||||
| 
 | ||||
| ```swift | ||||
| /* This only works in a playground, see SheetJSCore.swift for standalone use */ | ||||
| import JavaScriptCore; | ||||
| import PlaygroundSupport; | ||||
| 
 | ||||
| /* build path variable for the library */ | ||||
| let shared_dir = PlaygroundSupport.playgroundSharedDataDirectory; | ||||
| let lib_path = shared_dir.appendingPathComponent("xlsx.full.min.js"); | ||||
| 
 | ||||
| /* prepare JS context */ | ||||
| var context: JSContext! = JSContext(); | ||||
| var src = "var global = (function(){ return this; }).call(null);"; | ||||
| context.evaluateScript(src); | ||||
| 
 | ||||
| /* load library */ | ||||
| var lib = try? String(contentsOf: lib_path); | ||||
| context.evaluateScript(lib); | ||||
| let XLSX: JSValue! = context.objectForKeyedSubscript("XLSX"); | ||||
| 
 | ||||
| /* to verify the library was loaded, get the version string */ | ||||
| let XLSXversion: JSValue! = XLSX.objectForKeyedSubscript("version") | ||||
| var version  = XLSXversion.toString(); | ||||
| ``` | ||||
| 
 | ||||
| Binary strings can be passed back and forth using `String.Encoding.isoLatin1`: | ||||
| 
 | ||||
| ```swift | ||||
| /* parse sheetjs.xls */ | ||||
| let file_path = shared_dir.appendingPathComponent("sheetjs.xls"); | ||||
| let data: String! = try String(contentsOf: file_path, encoding: String.Encoding.isoLatin1); | ||||
| context.setObject(data, forKeyedSubscript: "payload" as (NSCopying & NSObjectProtocol)); | ||||
| src = "var wb = XLSX.read(payload, {type:'binary'});"; | ||||
| context.evaluateScript(src); | ||||
| 
 | ||||
| /* write to sheetjsw.xlsx  */ | ||||
| let out_path = shared_dir.appendingPathComponent("sheetjsw.xlsx"); | ||||
| src = "var out = XLSX.write(wb, {type:'binary', bookType:'xlsx'})"; | ||||
| context.evaluateScript(src); | ||||
| let outvalue: JSValue! = context.objectForKeyedSubscript("out"); | ||||
| var out: String! = outvalue.toString(); | ||||
| try? out.write(to: out_path, atomically: false, encoding: String.Encoding.isoLatin1); | ||||
| ``` | ||||
| 
 | ||||
| 
 | ||||
| ## Nashorn | ||||
| 
 | ||||
| Nashorn ships with Java 8.  It includes a command-line tool `jjs` for running JS | ||||
| scripts.  It is somewhat limited but does offer access to the full Java runtime. | ||||
| 
 | ||||
| The `load` function in `jjs` can load the minified source directly: | ||||
| 
 | ||||
| ```js | ||||
| var global = (function(){ return this; }).call(null); | ||||
| load('xlsx.full.min.js'); | ||||
| ``` | ||||
| 
 | ||||
| The Java `nio` API provides the `Files.readAllBytes` method to read a file into | ||||
| a byte array.  To use in `XLSX.read`, the demo copies the bytes into a plain JS | ||||
| array and calls `XLSX.read` with type `"array"`. | ||||
| 
 | ||||
| 
 | ||||
| ## Rhino | ||||
| 
 | ||||
| [Rhino](http://www.mozilla.org/rhino) is an ES3+ engine written in Java.  The | ||||
| `SheetJSRhino` class and `com.sheetjs` package show a complete JAR deployment, | ||||
| including the full XLSX source. | ||||
| 
 | ||||
| Due to code generation errors, optimization must be turned off: | ||||
| 
 | ||||
| ```java | ||||
| Context context = Context.enter(); | ||||
| context.setOptimizationLevel(-1); | ||||
| ``` | ||||
| 
 | ||||
| 
 | ||||
| ## ChakraCore | ||||
| 
 | ||||
| ChakraCore is an embeddable JS engine written in C++.  The library and binary | ||||
| distributions include a command-line tool `chakra` for running JS scripts. | ||||
| 
 | ||||
| The simplest way to interact with the engine is to pass Base64 strings. The make | ||||
| target builds a very simple payload with the data. | ||||
| 
 | ||||
| 
 | ||||
| ## Duktape | ||||
| 
 | ||||
| [Duktape](http://duktape.org/) is an embeddable JS engine written in C.  The | ||||
| amalgamation makes integration extremely simple!  It supports `Buffer` natively | ||||
| but should be sliced before processing: | ||||
| 
 | ||||
| ```C | ||||
| /* parse a C char array as a workbook object */ | ||||
| duk_push_external_buffer(ctx); | ||||
| duk_config_buffer(ctx, -1, buf, len); | ||||
| duk_put_global_string(ctx, "buf"); | ||||
| duk_eval_string_noresult("workbook = XLSX.read(buf.slice(0, buf.length), {type:'buffer'});"); | ||||
| 
 | ||||
| /* write a workbook object to a C char array */ | ||||
| duk_eval_string(ctx, "XLSX.write(workbook, {type:'array', bookType:'xlsx'})"); | ||||
| duk_size_t sz; | ||||
| char *buf = (char *)duk_get_buffer_data(ctx, -1, sz); | ||||
| duk_pop(ctx); | ||||
| ``` | ||||
| 
 | ||||
| 
 | ||||
| ## QuickJS | ||||
| 
 | ||||
| QuickJS is an embeddable JS engine written in C.  It provides a separate set of | ||||
| functions for interacting with the filesystem and the global object.  It can run | ||||
| the browser dist build. | ||||
| 
 | ||||
| The `global` object is available as `std.global`.  To make it visible to the | ||||
| loader, create a reference to itself: | ||||
| 
 | ||||
| ```js | ||||
| std.global.global = std.global; | ||||
| std.loadScript("xlsx.full.min.js"); | ||||
| ``` | ||||
| 
 | ||||
| The filesystem interaction mirrors POSIX, including separate allocations: | ||||
| 
 | ||||
| ```js | ||||
| /* read file */ | ||||
| var rh = std.open(filename, "rb"); rh.seek(0, std.SEEK_END); | ||||
| var sz = rh.tell(); rh.seek(); | ||||
| var ab = new ArrayBuffer(sz); rh.read(ab, 0, sz); rh.close(); | ||||
| var wb = XLSX.read(ab, {type: 'array'}); | ||||
| 
 | ||||
| /* write file */ | ||||
| var ab = XLSX.write(wb, {type: 'array'}); | ||||
| var wh = std.open("sheetjs.qjs.xlsx", "wb"); | ||||
| wh.write(out, 0, ab.byteLength); wh.close(); | ||||
| ``` | ||||
| 
 | ||||
| 
 | ||||
| ## Goja | ||||
| 
 | ||||
| Goja is a pure Go implementation of ECMAScript 5.  `[]byte` should be converted | ||||
| to a binary string in the engine: | ||||
| 
 | ||||
| ```go | ||||
| /* read file */ | ||||
| data, _ := ioutil.ReadFile("sheetjs.xlsx") | ||||
| 
 | ||||
| /* load into engine */ | ||||
| vm.Set("buf", data) | ||||
| 
 | ||||
| /* convert to binary string */ | ||||
| _, _ = vm.RunString("var bstr = ''; for(var i = 0; i < buf.length; ++i) bstr += String.fromCharCode(buf[i]);") | ||||
| 
 | ||||
| /* parse */ | ||||
| wb, _ = vm.RunString("wb = XLSX.read(bstr, {type:'binary', cellNF:true});") | ||||
| ``` | ||||
| 
 | ||||
| On the write side, `"base64"` strings can be decoded in Go: | ||||
| 
 | ||||
| ```go | ||||
| b64str, _ := vm.RunString("XLSX.write(wb, {type:'base64', bookType:'xlsx'})") | ||||
| buf, _ := base64.StdEncoding.DecodeString(b64str.String()) | ||||
| _ = ioutil.WriteFile("sheetjs.xlsx", buf, 0644) | ||||
| ``` | ||||
| 
 | ||||
| [](https://github.com/SheetJS/js-xlsx) | ||||
							
								
								
									
										37
									
								
								demos/altjs/SJSPlayground.swift
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										37
									
								
								demos/altjs/SJSPlayground.swift
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,37 @@ | ||||
| /* xlsx.js (C) 2013-present  SheetJS -- http://sheetjs.com */ | ||||
| /* This only works in a playground, see SheetJSCore.swift for standalone use */ | ||||
| import JavaScriptCore; | ||||
| import PlaygroundSupport; | ||||
| 
 | ||||
| /* build path variable for the library */ | ||||
| let shared_dir = PlaygroundSupport.playgroundSharedDataDirectory; | ||||
| let lib_path = shared_dir.appendingPathComponent("xlsx.full.min.js"); | ||||
| 
 | ||||
| /* prepare JS context */ | ||||
| var context: JSContext! = JSContext(); | ||||
| var src = "var global = (function(){ return this; }).call(null);"; | ||||
| context.evaluateScript(src); | ||||
| 
 | ||||
| /* load library */ | ||||
| var lib = try? String(contentsOf: lib_path); | ||||
| context.evaluateScript(lib); | ||||
| let XLSX: JSValue! = context.objectForKeyedSubscript("XLSX"); | ||||
| 
 | ||||
| /* to verify the library was loaded, get the version string */ | ||||
| let XLSXversion: JSValue! = XLSX.objectForKeyedSubscript("version") | ||||
| var version  = XLSXversion.toString(); | ||||
| 
 | ||||
| /* parse sheetjs.xls */ | ||||
| let file_path = shared_dir.appendingPathComponent("sheetjs.xls"); | ||||
| let data: String! = try String(contentsOf: file_path, encoding: String.Encoding.isoLatin1); | ||||
| context.setObject(data, forKeyedSubscript: "payload" as (NSCopying & NSObjectProtocol)!); | ||||
| src = "var wb = XLSX.read(payload, {type:'binary'});"; | ||||
| context.evaluateScript(src); | ||||
| 
 | ||||
| /* write to sheetjsw.xlsx  */ | ||||
| let out_path = shared_dir.appendingPathComponent("sheetjsw.xlsx"); | ||||
| src = "var out = XLSX.write(wb, {type:'binary', bookType:'xlsx'})"; | ||||
| context.evaluateScript(src); | ||||
| let outvalue: JSValue! = context.objectForKeyedSubscript("out"); | ||||
| var out: String! = outvalue.toString(); | ||||
| try? out.write(to: out_path, atomically: false, encoding: String.Encoding.isoLatin1); | ||||
							
								
								
									
										96
									
								
								demos/altjs/SheetJSCore.swift
									
									
									
									
									
										Executable file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										96
									
								
								demos/altjs/SheetJSCore.swift
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,96 @@ | ||||
| /* xlsx.js (C) 2013-present  SheetJS -- http://sheetjs.com */ | ||||
| import JavaScriptCore; | ||||
| 
 | ||||
| enum SJSError: Error { | ||||
|   case badJSContext; | ||||
|   case badJSWorkbook; | ||||
|   case badJSWorksheet; | ||||
| }; | ||||
| 
 | ||||
| class SJSWorksheet { | ||||
|   var context: JSContext!; | ||||
|   var wb: JSValue; var ws: JSValue; | ||||
|   var idx: Int32; | ||||
| 
 | ||||
|   func toCSV() throws -> String { | ||||
|     let XLSX: JSValue! = context.objectForKeyedSubscript("XLSX"); | ||||
|     let utils: JSValue! = XLSX.objectForKeyedSubscript("utils"); | ||||
|     let sheet_to_csv: JSValue! = utils.objectForKeyedSubscript("sheet_to_csv"); | ||||
|     return sheet_to_csv.call(withArguments: [ws]).toString(); | ||||
|   } | ||||
| 
 | ||||
|   init(ctx: JSContext, workbook: JSValue, worksheet: JSValue, idx: Int32) throws { | ||||
|     self.context = ctx; self.wb = workbook; self.ws = worksheet; self.idx = idx; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| class SJSWorkbook { | ||||
|   var context: JSContext!; | ||||
|   var wb: JSValue; var SheetNames: JSValue; var Sheets: JSValue; | ||||
| 
 | ||||
|   func getSheetAtIndex(idx: Int32) throws -> SJSWorksheet { | ||||
|     let SheetName: String = SheetNames.atIndex(Int(idx)).toString(); | ||||
|     let ws: JSValue! = Sheets.objectForKeyedSubscript(SheetName); | ||||
|     return try SJSWorksheet(ctx: context, workbook: wb, worksheet: ws, idx: idx); | ||||
|   } | ||||
| 
 | ||||
|   func writeBStr(bookType: String = "xlsx") throws -> String { | ||||
|     let XLSX: JSValue! = context.objectForKeyedSubscript("XLSX"); | ||||
|     context.evaluateScript(String(format: "var writeopts = {type:'binary', bookType:'%@'}", bookType)); | ||||
|     let writeopts: JSValue = context.objectForKeyedSubscript("writeopts"); | ||||
|     let writefunc: JSValue = XLSX.objectForKeyedSubscript("write"); | ||||
|     return writefunc.call(withArguments: [wb, writeopts]).toString(); | ||||
|   } | ||||
| 
 | ||||
|   init(ctx: JSContext, wb: JSValue) throws { | ||||
|     self.context = ctx; | ||||
|     self.wb = wb; | ||||
|     self.SheetNames = wb.objectForKeyedSubscript("SheetNames"); | ||||
|     self.Sheets = wb.objectForKeyedSubscript("Sheets"); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| class SheetJSCore { | ||||
|   var context: JSContext!; | ||||
|   var XLSX: JSValue!; | ||||
| 
 | ||||
|   func init_context() throws -> JSContext { | ||||
|     var context: JSContext! | ||||
|     do { | ||||
|       context = JSContext(); | ||||
|       context.exceptionHandler = { _, X in if let e = X { print(e.toString()!); }; }; | ||||
|       context.evaluateScript("var global = (function(){ return this; }).call(null);"); | ||||
|       context.evaluateScript("if(typeof wbs == 'undefined') wbs = [];"); | ||||
|       let src = try String(contentsOfFile: "xlsx.full.min.js"); | ||||
|       context.evaluateScript(src); | ||||
|       if context != nil { return context!; } | ||||
|     } catch { print(error.localizedDescription); } | ||||
|     throw SJSError.badJSContext; | ||||
|   } | ||||
| 
 | ||||
|   func version() throws -> String { | ||||
|     if let version = XLSX.objectForKeyedSubscript("version") { return version.toString(); } | ||||
|     throw SJSError.badJSContext; | ||||
|   } | ||||
| 
 | ||||
|   func readFile(file: String) throws -> SJSWorkbook { | ||||
|     let data: String! = try String(contentsOfFile: file, encoding: String.Encoding.isoLatin1); | ||||
|     return try readBStr(data: data); | ||||
|   } | ||||
| 
 | ||||
|   func readBStr(data: String) throws -> SJSWorkbook { | ||||
|     context.setObject(data, forKeyedSubscript: "payload" as (NSCopying & NSObjectProtocol)); | ||||
|     context.evaluateScript("var wb = XLSX.read(payload, {type:'binary'});"); | ||||
|     let wb: JSValue! = context.objectForKeyedSubscript("wb"); | ||||
|     if wb == nil { throw SJSError.badJSWorkbook; } | ||||
|     return try SJSWorkbook(ctx: context, wb: wb); | ||||
|   } | ||||
| 
 | ||||
|   init() throws { | ||||
|     do { | ||||
|       self.context = try init_context(); | ||||
|       self.XLSX = self.context.objectForKeyedSubscript("XLSX"); | ||||
|       if self.XLSX == nil { throw SJSError.badJSContext; } | ||||
|     } catch { print(error.localizedDescription); } | ||||
|   } | ||||
| } | ||||
							
								
								
									
										31
									
								
								demos/altjs/SheetJSRhino.java
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										31
									
								
								demos/altjs/SheetJSRhino.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| /* xlsx.js (C) 2013-present  SheetJS -- http://sheetjs.com */ | ||||
| /* vim: set ts=2: */ | ||||
| import com.sheetjs.SheetJS; | ||||
| import com.sheetjs.SheetJSFile; | ||||
| import com.sheetjs.SheetJSSheet; | ||||
| 
 | ||||
| public class SheetJSRhino { | ||||
|   public static void main(String args[]) throws Exception { | ||||
|     try { | ||||
|       SheetJS sjs = new SheetJS(); | ||||
| 
 | ||||
|       /* open file */ | ||||
|       SheetJSFile xl = sjs.read_file(args[0]); | ||||
| 
 | ||||
|       /* get sheetnames */ | ||||
|       String[] sheetnames = xl.get_sheet_names(); | ||||
|       System.err.println(sheetnames[0]); | ||||
| 
 | ||||
|       /* convert to CSV */ | ||||
|       SheetJSSheet sheet = xl.get_sheet(0); | ||||
|       String csv = sheet.get_csv(); | ||||
| 
 | ||||
|       System.out.println(csv); | ||||
| 
 | ||||
|     } catch(Exception e) { | ||||
|       throw e; | ||||
|     } finally { | ||||
|       SheetJS.close(); | ||||
|     } | ||||
|   } | ||||
| } | ||||
							
								
								
									
										3
									
								
								demos/altjs/chakra.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										3
									
								
								demos/altjs/chakra.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| /* xlsx.js (C) 2013-present  SheetJS -- http://sheetjs.com */ | ||||
| var wb = XLSX.read(payload, {type:'base64'}); | ||||
| console.log(XLSX.utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]])); | ||||
							
								
								
									
										51
									
								
								demos/altjs/com/sheetjs/JSHelper.java
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										51
									
								
								demos/altjs/com/sheetjs/JSHelper.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,51 @@ | ||||
| /* xlsx.js (C) 2013-present  SheetJS -- http://sheetjs.com */ | ||||
| /* vim: set ts=2: */ | ||||
| package com.sheetjs; | ||||
| 
 | ||||
| import java.lang.Integer; | ||||
| import java.lang.StringBuilder; | ||||
| import java.io.IOException; | ||||
| import java.nio.file.Files; | ||||
| import java.nio.file.Paths; | ||||
| import org.mozilla.javascript.Context; | ||||
| import org.mozilla.javascript.NativeArray; | ||||
| import org.mozilla.javascript.NativeObject; | ||||
| import org.mozilla.javascript.Scriptable; | ||||
| 
 | ||||
| public class JSHelper { | ||||
|   static String read_file(String file) throws IOException { | ||||
|     byte[] b = Files.readAllBytes(Paths.get(file)); | ||||
|     System.out.println(b.length); | ||||
|     StringBuilder sb = new StringBuilder(); | ||||
|     for(int i = 0; i < b.length; ++i) sb.append(Character.toString((char)(b[i] < 0 ? b[i] + 256 : b[i]))); | ||||
|     return sb.toString(); | ||||
|   } | ||||
| 
 | ||||
|   static Object get_object(String path, Object base) throws ObjectNotFoundException { | ||||
|     int idx = path.indexOf("."); | ||||
|     Scriptable b = (Scriptable)base; | ||||
|     if(idx == -1) return b.get(path, b); | ||||
|     Object o = b.get(path.substring(0,idx), b); | ||||
|     if(o == Scriptable.NOT_FOUND) throw new ObjectNotFoundException("not found: |" + path.substring(0,idx) + "|" + Integer.toString(idx)); | ||||
|     return get_object(path.substring(idx+1), (NativeObject)o); | ||||
|   } | ||||
| 
 | ||||
|   static Object[] get_array(String path, Object base) throws ObjectNotFoundException { | ||||
|     NativeArray arr = (NativeArray)get_object(path, base); | ||||
|     Object[] out = new Object[(int)arr.getLength()]; | ||||
|     int idx; | ||||
|     for(Object o : arr.getIds()) out[idx = (Integer)o] = arr.get(idx, arr); | ||||
|     return out; | ||||
|   } | ||||
| 
 | ||||
|   static String[] get_string_array(String path, Object base) throws ObjectNotFoundException { | ||||
|     NativeArray arr = (NativeArray)get_object(path, base); | ||||
|     String[] out = new String[(int)arr.getLength()]; | ||||
|     int idx; | ||||
|     for(Object o : arr.getIds()) out[idx = (Integer)o] = arr.get(idx, arr).toString(); | ||||
|     return out; | ||||
|   } | ||||
| 
 | ||||
|   public static void close() { Context.exit(); } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										10
									
								
								demos/altjs/com/sheetjs/ObjectNotFoundException.java
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										10
									
								
								demos/altjs/com/sheetjs/ObjectNotFoundException.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| /* xlsx.js (C) 2013-present  SheetJS -- http://sheetjs.com */ | ||||
| /* vim: set ts=2: */ | ||||
| package com.sheetjs; | ||||
| 
 | ||||
| import java.lang.Exception; | ||||
| 
 | ||||
| public class ObjectNotFoundException extends Exception { | ||||
|   public ObjectNotFoundException() {} | ||||
|   public ObjectNotFoundException(String message) { super(message); } | ||||
| } | ||||
							
								
								
									
										58
									
								
								demos/altjs/com/sheetjs/SheetJS.java
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										58
									
								
								demos/altjs/com/sheetjs/SheetJS.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,58 @@ | ||||
| /* xlsx.js (C) 2013-present  SheetJS -- http://sheetjs.com */ | ||||
| /* vim: set ts=2: */ | ||||
| package com.sheetjs; | ||||
| 
 | ||||
| import java.lang.Integer; | ||||
| import java.util.Scanner; | ||||
| import java.io.IOException; | ||||
| import java.io.File; | ||||
| import org.mozilla.javascript.Context; | ||||
| import org.mozilla.javascript.Function; | ||||
| import org.mozilla.javascript.NativeObject; | ||||
| import org.mozilla.javascript.Scriptable; | ||||
| 
 | ||||
| public class SheetJS { | ||||
|   public Scriptable scope; | ||||
|   public Context cx; | ||||
|   public NativeObject nXLSX; | ||||
| 
 | ||||
|   public SheetJS() throws Exception { | ||||
|     this.cx = Context.enter(); | ||||
|     this.scope = this.cx.initStandardObjects(); | ||||
| 
 | ||||
|     /* boilerplate */ | ||||
|     cx.setOptimizationLevel(-1); | ||||
|     String s = "var global = (function(){ return this; }).call(null);"; | ||||
|     cx.evaluateString(scope, s, "<cmd>", 1, null); | ||||
| 
 | ||||
|     /* eval library */ | ||||
|     s = new Scanner(SheetJS.class.getResourceAsStream("/xlsx.full.min.js")).useDelimiter("\\Z").next(); | ||||
|     //s = new Scanner(new File("xlsx.full.min.js")).useDelimiter("\\Z").next(); | ||||
|     cx.evaluateString(scope, s, "<cmd>", 1, null); | ||||
| 
 | ||||
|     /* grab XLSX variable */ | ||||
|     Object XLSX = scope.get("XLSX", scope); | ||||
|     if(XLSX == Scriptable.NOT_FOUND) throw new Exception("XLSX not found"); | ||||
|     this.nXLSX = (NativeObject)XLSX; | ||||
|   } | ||||
| 
 | ||||
|   public SheetJSFile read_file(String filename) throws IOException, ObjectNotFoundException { | ||||
|     /* open file */ | ||||
|     String d = JSHelper.read_file(filename); | ||||
| 
 | ||||
|     /* options argument */ | ||||
|     NativeObject q = (NativeObject)this.cx.evaluateString(this.scope, "q = {'type':'binary', 'WTF':1};", "<cmd>", 2, null); | ||||
| 
 | ||||
|     /* set up function arguments */ | ||||
|     Object args[] = {d, q}; | ||||
| 
 | ||||
|     /* call read -> wb workbook */ | ||||
|     Function readfunc = (Function)JSHelper.get_object("XLSX.read",this.scope); | ||||
|     NativeObject wb = (NativeObject)readfunc.call(this.cx, this.scope, this.nXLSX, args); | ||||
| 
 | ||||
|     return new SheetJSFile(wb, this); | ||||
|   } | ||||
| 
 | ||||
|   public static void close() { JSHelper.close(); } | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										24
									
								
								demos/altjs/com/sheetjs/SheetJSFile.java
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										24
									
								
								demos/altjs/com/sheetjs/SheetJSFile.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| /* xlsx.js (C) 2013-present  SheetJS -- http://sheetjs.com */ | ||||
| /* vim: set ts=2: */ | ||||
| package com.sheetjs; | ||||
| 
 | ||||
| import org.mozilla.javascript.NativeObject; | ||||
| import org.mozilla.javascript.Function; | ||||
| 
 | ||||
| public class SheetJSFile { | ||||
|   public NativeObject wb; | ||||
|   public SheetJS sheetjs; | ||||
|   public SheetJSFile() {} | ||||
|   public SheetJSFile(NativeObject wb, SheetJS sheetjs) { this.wb = wb; this.sheetjs = sheetjs; } | ||||
|   public String[] get_sheet_names() { | ||||
|     try { | ||||
|       return JSHelper.get_string_array("SheetNames", this.wb); | ||||
|     } catch(ObjectNotFoundException e) { | ||||
|       return null; | ||||
|     } | ||||
|   } | ||||
|   public SheetJSSheet get_sheet(int idx) throws ObjectNotFoundException { | ||||
|     return new SheetJSSheet(this, idx); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										29
									
								
								demos/altjs/com/sheetjs/SheetJSSheet.java
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										29
									
								
								demos/altjs/com/sheetjs/SheetJSSheet.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | ||||
| /* xlsx.js (C) 2013-present  SheetJS -- http://sheetjs.com */ | ||||
| /* vim: set ts=2: */ | ||||
| package com.sheetjs; | ||||
| 
 | ||||
| import org.mozilla.javascript.Function; | ||||
| import org.mozilla.javascript.NativeObject; | ||||
| 
 | ||||
| public class SheetJSSheet { | ||||
|   public NativeObject ws; | ||||
|   public SheetJSFile wb; | ||||
|   public SheetJSSheet(SheetJSFile wb, int idx) throws ObjectNotFoundException { | ||||
|     this.wb = wb; | ||||
|     this.ws = (NativeObject)JSHelper.get_object("Sheets." + wb.get_sheet_names()[idx],wb.wb); | ||||
|   } | ||||
|   public String get_range() throws ObjectNotFoundException { | ||||
|     return JSHelper.get_object("!ref",this.ws).toString(); | ||||
|   } | ||||
|   public String get_string_value(String address) throws ObjectNotFoundException { | ||||
|     return JSHelper.get_object(address + ".v",this.ws).toString(); | ||||
|   } | ||||
| 
 | ||||
|   public String get_csv() throws ObjectNotFoundException { | ||||
|     Function csvify = (Function)JSHelper.get_object("XLSX.utils.sheet_to_csv",this.wb.sheetjs.scope); | ||||
|     Object csvArgs[] = {this.ws}; | ||||
|     Object csv = csvify.call(this.wb.sheetjs.cx, this.wb.sheetjs.scope, this.wb.sheetjs.scope, csvArgs); | ||||
|     return csv.toString(); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										16
									
								
								demos/altjs/duktape.sh
									
									
									
									
									
										Executable file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										16
									
								
								demos/altjs/duktape.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,16 @@ | ||||
| #!/bin/bash | ||||
| DUKTAPE_VER=2.6.0 | ||||
| if [ ! -e duktape-$DUKTAPE_VER ]; then | ||||
| 	if [ ! -e duktape-$DUKTAPE_VER.tar ]; then | ||||
| 		if [ ! -e duktape-$DUKTAPE_VER.tar.xz ]; then | ||||
| 			curl -O https://duktape.org/duktape-$DUKTAPE_VER.tar.xz | ||||
| 		fi | ||||
| 		xz -d duktape-$DUKTAPE_VER.tar.xz | ||||
| 	fi | ||||
| 	tar -xf duktape-$DUKTAPE_VER.tar | ||||
| fi | ||||
| 
 | ||||
| for f in duktape.{c,h} duk_config.h; do | ||||
| 	cp duktape-$DUKTAPE_VER/src/$f . | ||||
| done | ||||
| 
 | ||||
							
								
								
									
										3
									
								
								demos/altjs/global.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										3
									
								
								demos/altjs/global.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| /* xlsx.js (C) 2013-present  SheetJS -- http://sheetjs.com */ | ||||
| var global = (function(){ return this; }).call(null); | ||||
| 
 | ||||
							
								
								
									
										71
									
								
								demos/altjs/goja.go
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										71
									
								
								demos/altjs/goja.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,71 @@ | ||||
| package main | ||||
| 
 | ||||
| import ( | ||||
| 	b64 "encoding/base64" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"io/ioutil" | ||||
| 	"github.com/dop251/goja" | ||||
| ) | ||||
| 
 | ||||
| func safe_run_file(vm *goja.Runtime, file string) { | ||||
| 	data, err := ioutil.ReadFile(file) | ||||
| 	if err != nil { panic(err) } | ||||
| 	src := string(data) | ||||
| 	_, err = vm.RunString(src) | ||||
| 	if err != nil { panic(err) } | ||||
| } | ||||
| 
 | ||||
| func eval_string(vm *goja.Runtime, cmd string) goja.Value { | ||||
| 	v, err := vm.RunString(cmd) | ||||
| 	if err != nil { panic(err) } | ||||
| 	return v | ||||
| } | ||||
| 
 | ||||
| func write_type(vm *goja.Runtime, t string) { | ||||
| 	/* due to some wonkiness with array passing, use base64 */ | ||||
| 	b64str := eval_string(vm, "XLSX.write(wb, {type:'base64', bookType:'" + t + "'})") | ||||
| 	buf, err := b64.StdEncoding.DecodeString(b64str.String()); | ||||
| 	if err != nil { panic(err) } | ||||
| 	err = ioutil.WriteFile("sheetjsg." + t, buf, 0644) | ||||
| 	if err != nil { panic(err) } | ||||
| } | ||||
| 
 | ||||
| func main() { | ||||
| 	vm := goja.New() | ||||
| 
 | ||||
| 	/* initialize */ | ||||
| 	eval_string(vm, "if(typeof global == 'undefined') global = (function(){ return this; }).call(null);") | ||||
| 
 | ||||
| 	/* load library */ | ||||
| 	safe_run_file(vm, "shim.min.js") | ||||
| 	safe_run_file(vm, "xlsx.full.min.js") | ||||
| 
 | ||||
| 	/* get version string */ | ||||
| 	v := eval_string(vm, "XLSX.version") | ||||
| 	fmt.Printf("SheetJS library version %s\n", v) | ||||
| 
 | ||||
| 	/* read file */ | ||||
| 	data, err := ioutil.ReadFile(os.Args[1]) | ||||
| 	if err != nil { panic(err) } | ||||
| 	vm.Set("buf", data) | ||||
| 	fmt.Printf("Loaded file %s\n", os.Args[1]) | ||||
| 
 | ||||
| 	/* parse workbook */ | ||||
| 	eval_string(vm, "var bstr = ''; for(var i = 0; i < buf.length; ++i) bstr += String.fromCharCode(buf[i]);") | ||||
| 	eval_string(vm, "wb = XLSX.read(bstr, {type:'binary', cellNF:true});") | ||||
| 	eval_string(vm, "ws = wb.Sheets[wb.SheetNames[0]]") | ||||
| 
 | ||||
| 	/* print CSV */ | ||||
| 	csv := eval_string(vm, "XLSX.utils.sheet_to_csv(ws)") | ||||
| 	fmt.Printf("%s\n", csv) | ||||
| 
 | ||||
| 	/* change cell A1 to 3 */ | ||||
| 	eval_string(vm, "ws['A1'].v = 3; delete ws['A1'].w;") | ||||
| 
 | ||||
| 	/* write file */ | ||||
| 	//write_type(vm, "xlsb")
 | ||||
| 	//write_type(vm, "xlsx")
 | ||||
| 	write_type(vm, "xls") | ||||
| 	write_type(vm, "csv") | ||||
| } | ||||
							
								
								
									
										21
									
								
								demos/altjs/main.swift
									
									
									
									
									
										Executable file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										21
									
								
								demos/altjs/main.swift
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,21 @@ | ||||
| /* xlsx.js (C) 2013-present  SheetJS -- http://sheetjs.com */ | ||||
| 
 | ||||
| let sheetjs = try SheetJSCore(); | ||||
| 
 | ||||
| try print(sheetjs.version()); | ||||
| 
 | ||||
| let filenames: [[String]] = [ | ||||
|   ["xlsx", "xlsx"], | ||||
|   ["xlsb", "xlsb"], | ||||
|   ["biff8.xls", "xls"], | ||||
|   ["xml.xls", "xlml"] | ||||
| ]; | ||||
| 
 | ||||
| for fn in filenames { | ||||
|   let wb: SJSWorkbook = try sheetjs.readFile(file: "sheetjs." + fn[0]); | ||||
|   let ws: SJSWorksheet = try wb.getSheetAtIndex(idx: 0); | ||||
|   let csv: String = try ws.toCSV(); | ||||
|   print(csv); | ||||
|   let wbout: String = try wb.writeBStr(bookType: fn[1]); | ||||
|   try wbout.write(toFile: "sheetjsswift." + fn[0], atomically: false, encoding: String.Encoding.isoLatin1); | ||||
| } | ||||
							
								
								
									
										36
									
								
								demos/altjs/nashorn.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										36
									
								
								demos/altjs/nashorn.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| #!/usr/bin/env jjs
 | ||||
| /* xlsx.js (C) 2013-present  SheetJS -- http://sheetjs.com */ | ||||
| 
 | ||||
| /* load module */ | ||||
| var global = (function(){ return this; }).call(null); | ||||
| load('xlsx.full.min.js'); | ||||
| 
 | ||||
| /* helper to convert byte array to plain JS array */ | ||||
| function b2a(b) { | ||||
| 	var out = new Array(b.length); | ||||
| 	for(var i = 0; i < out.length; i++) out[i] = (b[i] < 0 ? b[i] + 256 : b[i]); | ||||
| 	return out; | ||||
| } | ||||
| 
 | ||||
| function process_file(path) { | ||||
| 	java.lang.System.out.println(path); | ||||
| 
 | ||||
| 	/* read file */ | ||||
| 	var path = java.nio.file.Paths.get(path); | ||||
| 	var bytes = java.nio.file.Files.readAllBytes(path); | ||||
| 	var u8a = b2a(bytes); | ||||
| 
 | ||||
| 	/* read data */ | ||||
| 	var wb = XLSX.read(u8a, {type:"array"}); | ||||
| 
 | ||||
| 	/* get first worksheet as an array of arrays */ | ||||
| 	var ws = wb.Sheets[wb.SheetNames[0]]; | ||||
| 	var js = XLSX.utils.sheet_to_json(ws, {header:1}); | ||||
| 
 | ||||
| 	/* print out every line */ | ||||
| 	js.forEach(function(l) { java.lang.System.out.println(JSON.stringify(l)); }); | ||||
| } | ||||
| 
 | ||||
| process_file('sheetjs.xlsx'); | ||||
| process_file('sheetjs.xlsb'); | ||||
| process_file('sheetjs.biff8.xls'); | ||||
							
								
								
									
										25
									
								
								demos/altjs/qjs.js
									
									
									
									
									
										Executable file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										25
									
								
								demos/altjs/qjs.js
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,25 @@ | ||||
| #!/usr/bin/env qjs
 | ||||
| /* xlsx.js (C) 2013-present  SheetJS -- http://sheetjs.com */ | ||||
| /* load XLSX */ | ||||
| std.global.global = std.global; | ||||
| std.loadScript("xlsx.full.min.js"); | ||||
| 
 | ||||
| /* read contents of file */ | ||||
| var rh = std.open("sheetjs.xlsx", "rb"); | ||||
| rh.seek(0, std.SEEK_END); | ||||
| var sz = rh.tell(); | ||||
| var ab = new ArrayBuffer(sz); | ||||
| rh.seek(); | ||||
| rh.read(ab, 0, sz); | ||||
| rh.close(); | ||||
| 
 | ||||
| /* parse file */ | ||||
| var wb = XLSX.read(ab, {type: 'array'}); | ||||
| 
 | ||||
| /* write array */ | ||||
| var out = XLSX.write(wb, {type: 'array'}); | ||||
| 
 | ||||
| /* write contents to file */ | ||||
| var wh = std.open("sheetjs.qjs.xlsx", "wb"); | ||||
| wh.write(out, 0, out.byteLength); | ||||
| wh.close(); | ||||
							
								
								
									
										110
									
								
								demos/altjs/sheetjs.duk.c
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										110
									
								
								demos/altjs/sheetjs.duk.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,110 @@ | ||||
| /* xlsx.js (C) 2013-present  SheetJS -- http://sheetjs.com */ | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include "duktape.h" | ||||
| 
 | ||||
| #define FAIL_LOAD { \ | ||||
| 	duk_push_undefined(ctx); \ | ||||
| 	perror("Error in load_file"); \ | ||||
| 	return 1; \ | ||||
| } | ||||
| 
 | ||||
| static char *read_file(const char *filename, size_t *sz) { | ||||
| 	FILE *f = fopen(filename, "rb"); | ||||
| 	if(!f) return NULL; | ||||
| 	long fsize; { fseek(f, 0, SEEK_END); fsize = ftell(f); fseek(f, 0, SEEK_SET); } | ||||
| 	char *buf = (char *)malloc(fsize * sizeof(char)); | ||||
| 	*sz = fread((void *) buf, 1, fsize, f); | ||||
| 	fclose(f); | ||||
| 	return buf; | ||||
| } | ||||
| 
 | ||||
| static duk_int_t eval_file(duk_context *ctx, const char *filename) { | ||||
| 	size_t len; char *buf = read_file(filename, &len); | ||||
| 	if(!buf) FAIL_LOAD | ||||
| 
 | ||||
| 	duk_push_lstring(ctx, (const char *)buf, (duk_size_t)len); | ||||
| 	duk_int_t retval = duk_peval(ctx); | ||||
| 	duk_pop(ctx); | ||||
| 	return retval; | ||||
| } | ||||
| 
 | ||||
| static duk_int_t load_file(duk_context *ctx, const char *filename, const char *var) { | ||||
| 	size_t len; char *buf = read_file(filename, &len); | ||||
| 	if(!buf) FAIL_LOAD | ||||
| 
 | ||||
| 	duk_push_external_buffer(ctx); | ||||
| 	duk_config_buffer(ctx, -1, buf, len); | ||||
| 	duk_put_global_string(ctx, var); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static duk_int_t save_file(duk_context *ctx, const char *filename, const char *var) { | ||||
| 	duk_get_global_string(ctx, var); | ||||
| 	duk_size_t sz; | ||||
| 	char *buf = (char *)duk_get_buffer_data(ctx, -1, &sz); | ||||
| 
 | ||||
| 	if(!buf) return 1; | ||||
| 	FILE *f = fopen(filename, "wb"); fwrite(buf, 1, sz, f); fclose(f); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| #define FAIL(cmd) { \ | ||||
| 	printf("error in %s: %s\n", cmd, duk_safe_to_string(ctx, -1)); \ | ||||
| 	duk_destroy_heap(ctx); \ | ||||
| 	return res; \ | ||||
| } | ||||
| 
 | ||||
| #define DOIT(cmd) duk_eval_string_noresult(ctx, cmd); | ||||
| int main(int argc, char *argv[]) { | ||||
| 	duk_int_t res = 0; | ||||
| 
 | ||||
| 	/* initialize */ | ||||
| 	duk_context *ctx = duk_create_heap_default(); | ||||
| 	/* duktape does not expose a standard "global" by default */ | ||||
| 	DOIT("var global = (function(){ return this; }).call(null);"); | ||||
| 
 | ||||
| 	/* load library */ | ||||
| 	res = eval_file(ctx, "shim.min.js"); | ||||
| 	if(res != 0) FAIL("shim load") | ||||
| 	res = eval_file(ctx, "xlsx.full.min.js"); | ||||
| 	if(res != 0) FAIL("library load") | ||||
| 
 | ||||
| 	/* get version string */ | ||||
| 	duk_eval_string(ctx, "XLSX.version"); | ||||
| 	printf("SheetJS library version %s\n", duk_get_string(ctx, -1)); | ||||
| 	duk_pop(ctx); | ||||
| 
 | ||||
| 	/* read file */ | ||||
| 	res = load_file(ctx, argv[1], "buf"); | ||||
| 	if(res != 0) FAIL("file load") | ||||
| 	printf("Loaded file %s\n", argv[1]); | ||||
| 
 | ||||
| 	/* parse workbook */ | ||||
| 	DOIT("wb = XLSX.read(buf, {type:'buffer', cellNF:true});"); | ||||
| 	DOIT("ws = wb.Sheets[wb.SheetNames[0]]"); | ||||
| 
 | ||||
| 	/* print CSV */ | ||||
| 	duk_eval_string(ctx, "XLSX.utils.sheet_to_csv(ws)"); | ||||
| 	printf("%s\n", duk_get_string(ctx, -1)); | ||||
| 	duk_pop(ctx); | ||||
| 
 | ||||
| 	/* change cell A1 to 3 */ | ||||
| 	DOIT("ws['A1'].v = 3; delete ws['A1'].w;"); | ||||
| 
 | ||||
| 	/* write file */ | ||||
| #define WRITE_TYPE(BOOKTYPE) \ | ||||
| 	DOIT("newbuf = (XLSX.write(wb, {type:'array', bookType:'" BOOKTYPE "'}));");\ | ||||
| 	res = save_file(ctx, "sheetjsw." BOOKTYPE, "newbuf");\ | ||||
| 	if(res != 0) FAIL("save sheetjsw." BOOKTYPE) | ||||
| 
 | ||||
| 	WRITE_TYPE("xlsb") | ||||
| 	WRITE_TYPE("xlsx") | ||||
| 	WRITE_TYPE("xls") | ||||
| 	WRITE_TYPE("csv") | ||||
| 
 | ||||
| 	/* cleanup */ | ||||
| 	duk_destroy_heap(ctx); | ||||
| 	return res; | ||||
| } | ||||
							
								
								
									
										10
									
								
								demos/angular/README.md
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										10
									
								
								demos/angular/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| # AngularJS | ||||
| 
 | ||||
| The content has been reorganized; | ||||
| 
 | ||||
| - [The "Legacy Frameworks" section](https://docs.sheetjs.com/docs/getting-started/demos/legacy#angularjs) | ||||
|   covers the AngularJS basics. | ||||
| - [The "Angular UI Grid" section](https://docs.sheetjs.com/docs/getting-started/demos/legacy#angularjs) | ||||
|   covers the integration with Angular UI Grid. | ||||
| 
 | ||||
| [](https://github.com/SheetJS/js-xlsx) | ||||
							
								
								
									
										23
									
								
								demos/angular2/.angular-cli.json
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										23
									
								
								demos/angular2/.angular-cli.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | ||||
| { | ||||
|   "$schema": "./node_modules/@angular/cli/lib/config/schema.json", | ||||
|   "project": { | ||||
|     "name": "angular2" | ||||
|   }, | ||||
|   "apps": [ | ||||
|     { | ||||
|       "root": "src", | ||||
|       "outDir": "dist", | ||||
|       "index": "index.html", | ||||
|       "main": "main.ts", | ||||
|       "polyfills": "polyfills.ts", | ||||
|       "test": "test.ts", | ||||
|       "tsconfig": "tsconfig.app.json", | ||||
|       "prefix": "app", | ||||
|       "scripts": [] | ||||
|     } | ||||
|   ], | ||||
|   "defaults": { | ||||
|     "styleExt": "css", | ||||
|     "component": {} | ||||
|   } | ||||
| } | ||||
							
								
								
									
										6
									
								
								demos/angular2/.eslintrc
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										6
									
								
								demos/angular2/.eslintrc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| { | ||||
| 	"parser": "@typescript-eslint/parser", | ||||
| 	"extends": [ | ||||
| 		"eslint:recommended" | ||||
| 	] | ||||
| } | ||||
							
								
								
									
										1
									
								
								demos/angular2/.gitattributes
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										1
									
								
								demos/angular2/.gitattributes
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| *.*-ng*           linguist-generated=true binary | ||||
							
								
								
									
										8
									
								
								demos/angular2/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										8
									
								
								demos/angular2/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| dist | ||||
| hooks | ||||
| SheetJSIonic | ||||
| SheetJSNS | ||||
| angular.json | ||||
| tsconfig.app.json | ||||
| src/polyfills.ts | ||||
| .angular | ||||
							
								
								
									
										45
									
								
								demos/angular2/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										45
									
								
								demos/angular2/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,45 @@ | ||||
| .PHONY: ng2 ng4 ng5 ng6 ng7 ng8 ng9 ng10 ng11 ng12 ng13 | ||||
| ng2 ng4 ng5 ng6 ng7 ng8 ng9 ng10 ng11 ng12 ng13: | ||||
| 	rm -f angular.json tsconfig.app.json src/polyfills.ts | ||||
| 	cp versions/package.json-$@ package.json | ||||
| 	if [ -e versions/angular.json-$@ ]; then cp versions/angular.json-$@ angular.json; fi | ||||
| 	if [ -e versions/tsconfig.app.json-$@ ]; then cp versions/tsconfig.app.json-$@ tsconfig.app.json; fi | ||||
| 	if [ -e versions/polyfills.ts-$@ ]; then cp versions/polyfills.ts-$@ src/polyfills.ts; fi | ||||
| 	rm -rf node_modules | ||||
| 	if [ ! -e node_modules ]; then mkdir node_modules; fi | ||||
| 	npm install | ||||
| 	if [ ! -e node_modules/xlsx ]; then cd node_modules; ln -s ../../../ xlsx; cd -; fi | ||||
| 	npm run build | ||||
| 
 | ||||
| .PHONY: refresh | ||||
| refresh: ## refresh the `xlsx` symlink to force angular to rebuild
 | ||||
| 	rm -rf .angular/ | ||||
| 	rm -f node_modules/xlsx | ||||
| 	cd node_modules; ln -s ../../../ xlsx; cd - | ||||
| 	touch node_modules/xlsx | ||||
| 
 | ||||
| .PHONY: all | ||||
| all: | ||||
| 	for i in 2 4 5 6 7 8 9 10 11 12 13; do make ng$$i; done | ||||
| 
 | ||||
| .PHONY: ionic | ||||
| ionic: | ||||
| 	bash ./ionic.sh | ||||
| 
 | ||||
| .PHONY: ios android browser | ||||
| ios browser: ionic | ||||
| 	cd SheetJSIonic; ionic cordova emulate $@ </dev/null; cd - | ||||
| android: ionic | ||||
| 	cd SheetJSIonic; ionic cordova prepare $@ </dev/null; ionic cordova emulate $@ </dev/null; cd - | ||||
| 
 | ||||
| 
 | ||||
| .PHONY: nativescript | ||||
| nativescript: | ||||
| 	bash ./nscript.sh | ||||
| 
 | ||||
| .PHONY: ns-ios ns-android | ||||
| ns-ios: nativescript | ||||
| 	cd SheetJSNS; ns run ios; cd - | ||||
| ns-android: nativescript | ||||
| 	cd SheetJSNS; ns run android; cd - | ||||
| 
 | ||||
							
								
								
									
										185
									
								
								demos/angular2/README.md
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										185
									
								
								demos/angular2/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,185 @@ | ||||
| # Angular 2+ | ||||
| 
 | ||||
| The ESM build can be imported directly from TS code with: | ||||
| 
 | ||||
| ```typescript | ||||
| import { read, utils, writeFileXLSX } from 'xlsx'; | ||||
| ``` | ||||
| 
 | ||||
| This demo uses an array of arrays (type `Array<Array<any>>`) as the core state. | ||||
| The component template includes a file input element, a table that updates with | ||||
| the data, and a button to export the data. | ||||
| 
 | ||||
| Other scripts in this demo show: | ||||
| - `ionic` deployment for iOS, android, and browser | ||||
| - `nativescript` deployment for iOS and android | ||||
| 
 | ||||
| ## Array of Arrays | ||||
| 
 | ||||
| `Array<Array<any>>` neatly maps to a table with `ngFor`: | ||||
| 
 | ||||
| ```html | ||||
| <table class="sjs-table"> | ||||
|   <tr *ngFor="let row of data"> | ||||
|     <td *ngFor="let val of row"> | ||||
|       {{val}} | ||||
|     </td> | ||||
|   </tr> | ||||
| </table> | ||||
| ``` | ||||
| 
 | ||||
| The `aoa_to_sheet` utility function returns a worksheet.  Exporting is simple: | ||||
| 
 | ||||
| ```typescript | ||||
| /* generate worksheet */ | ||||
| const ws: XLSX.WorkSheet = XLSX.utils.aoa_to_sheet(this.data); | ||||
| 
 | ||||
| /* generate workbook and add the worksheet */ | ||||
| const wb: XLSX.WorkBook = XLSX.utils.book_new(); | ||||
| XLSX.utils.book_append_sheet(wb, ws, 'Sheet1'); | ||||
| 
 | ||||
| /* save to file */ | ||||
| XLSX.writeFile(wb, 'SheetJS.xlsx'); | ||||
| ``` | ||||
| 
 | ||||
| `sheet_to_json` with the option `header:1` makes importing simple: | ||||
| 
 | ||||
| ```typescript | ||||
| /* <input type="file" (change)="onFileChange($event)" multiple="false" /> */ | ||||
| /* ... (within the component class definition) ... */ | ||||
|   onFileChange(evt: any) { | ||||
|     /* wire up file reader */ | ||||
|     const target: DataTransfer = <DataTransfer>(evt.target); | ||||
|     if (target.files.length !== 1) throw new Error('Cannot use multiple files'); | ||||
|     const reader: FileReader = new FileReader(); | ||||
|     reader.onload = (e: any) => { | ||||
|       /* read workbook */ | ||||
|       const ab: ArrayBuffer = e.target.result; | ||||
|       const wb: XLSX.WorkBook = XLSX.read(ab); | ||||
| 
 | ||||
|       /* grab first sheet */ | ||||
|       const wsname: string = wb.SheetNames[0]; | ||||
|       const ws: XLSX.WorkSheet = wb.Sheets[wsname]; | ||||
| 
 | ||||
|       /* save data */ | ||||
|       this.data = <AOA>(XLSX.utils.sheet_to_json(ws, {header: 1})); | ||||
|     }; | ||||
|     reader.readAsArrayBuffer(target.files[0]); | ||||
|   } | ||||
| ``` | ||||
| 
 | ||||
| ## Switching between Angular versions | ||||
| 
 | ||||
| Modules that work with Angular 2 largely work as-is with Angular 4+.  Switching | ||||
| between versions is mostly a matter of installing the correct version of the | ||||
| core and associated modules.  This demo includes `package.json-angular#` files | ||||
| for every major version of Angular up to 12. | ||||
| 
 | ||||
| To test a particular Angular version, overwrite `package.json`: | ||||
| 
 | ||||
| ```bash | ||||
| # switch to Angular 2 | ||||
| $ cp package.json-ng2 package.json | ||||
| $ npm install | ||||
| $ ng serve | ||||
| ``` | ||||
| 
 | ||||
| Note: when running the demos, Angular 2 requires Node <= 14.  This is due to a | ||||
| tooling issue with `ng` and does not affect browser use. | ||||
| 
 | ||||
| ## XLSX Symbolic Link | ||||
| 
 | ||||
| In this tree, `node_modules/xlsx` is a link pointing back to the root.  This | ||||
| enables testing the development version of the library.  In order to use this | ||||
| demo in other applications, add the `xlsx` dependency: | ||||
| 
 | ||||
| ```bash | ||||
| $ npm install --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz | ||||
| ``` | ||||
| 
 | ||||
| ## SystemJS Configuration | ||||
| 
 | ||||
| The default angular-cli configuration requires no additional configuration. | ||||
| 
 | ||||
| Some deployments use the SystemJS loader, which does require configuration.  The | ||||
| SystemJS example shows the required meta and map settings: | ||||
| 
 | ||||
| ```js | ||||
| SystemJS.config({ | ||||
|   meta: { | ||||
|     'xlsx': { | ||||
|       exports: 'XLSX' // <-- tell SystemJS to expose the XLSX variable | ||||
|     } | ||||
|   }, | ||||
|   map: { | ||||
|     'xlsx': 'xlsx.full.min.js', // <-- make sure xlsx.full.min.js is in same dir | ||||
|     'fs': '',     // <--| | ||||
|     'crypto': '', // <--| suppress native node modules | ||||
|     'stream': ''  // <--| | ||||
|   } | ||||
| }); | ||||
| ``` | ||||
| 
 | ||||
| ## Ionic | ||||
| 
 | ||||
| <img src="screen.png" width="400px"/> | ||||
| 
 | ||||
| Reproducing the full project is a little bit tricky.  The included `ionic.sh` | ||||
| script performs the necessary installation steps. | ||||
| 
 | ||||
| `Array<Array<any>>` neatly maps to a table with `ngFor`: | ||||
| 
 | ||||
| ```html | ||||
| <ion-grid> | ||||
|   <ion-row *ngFor="let row of data"> | ||||
|     <ion-col *ngFor="let val of row"> | ||||
|       {{val}} | ||||
|     </ion-col> | ||||
|   </ion-row> | ||||
| </ion-grid> | ||||
| ``` | ||||
| 
 | ||||
| 
 | ||||
| `@ionic-native/file` reads and writes files on devices. `readAsArrayBuffer` | ||||
| returns `ArrayBuffer` objects suitable for `array` type, and `array` type can | ||||
| be converted to blobs that can be exported with `writeFile`: | ||||
| 
 | ||||
| ```typescript | ||||
| /* read a workbook */ | ||||
| const ab: ArrayBuffer = await this.file.readAsArrayBuffer(url, filename); | ||||
| const wb: XLSX.WorkBook = XLSX.read(bstr, {type: 'array'}); | ||||
| 
 | ||||
| /* write a workbook */ | ||||
| const wbout: ArrayBuffer = XLSX.write(wb, { bookType: 'xlsx', type: 'array' }); | ||||
| let blob = new Blob([wbout], {type: 'application/octet-stream'}); | ||||
| this.file.writeFile(url, filename, blob, {replace: true}); | ||||
| ``` | ||||
| 
 | ||||
| ## NativeScript | ||||
| 
 | ||||
| Reproducing the full project is a little bit tricky.  The included `nscript.sh` | ||||
| script performs the necessary installation steps and adds the necessary shims | ||||
| for `async` support.  Due to incompatibilities with NativeScript and TypeScript | ||||
| definitions, apps should require the `xlsx.full.min.js` file directly: | ||||
| 
 | ||||
| ```typescript | ||||
| const XLSX = require("./xlsx.full.min.js"); | ||||
| ``` | ||||
| 
 | ||||
| The `ISO_8859_1` encoding from the text module specifies `"binary"` strings. | ||||
| `File#readText` and `File#writeText` reads and writes files: | ||||
| 
 | ||||
| ```typescript | ||||
| /* read a workbook */ | ||||
| const bstr: string = await file.readText(encoding.ISO_8859_1); | ||||
| const wb = XLSX.read(bstr, { type: "binary" }); | ||||
| 
 | ||||
| /* write a workbook */ | ||||
| const wbout: string = XLSX.write(wb, { bookType: 'xlsx', type: 'binary' }); | ||||
| await file.writeText(wbout, encoding.ISO_8859_1); | ||||
| ``` | ||||
| 
 | ||||
| Note: some versions of NativeScript do not properly support typed arrays or | ||||
| binary strings.  See <https://github.com/NativeScript/NativeScript/issues/9586> | ||||
| 
 | ||||
| [](https://github.com/SheetJS/js-xlsx) | ||||
							
								
								
									
										22
									
								
								demos/angular2/ionic-app.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										22
									
								
								demos/angular2/ionic-app.module.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | ||||
| /* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */ | ||||
| /* vim: set ts=2: */ | ||||
| /* NOTE: this file exists because `File` must be added as a provider */ | ||||
| import { NgModule } from '@angular/core'; | ||||
| import { BrowserModule } from '@angular/platform-browser'; | ||||
| import { RouteReuseStrategy } from '@angular/router'; | ||||
| 
 | ||||
| import { IonicModule, IonicRouteStrategy } from '@ionic/angular'; | ||||
| 
 | ||||
| import { AppComponent } from './app.component'; | ||||
| import { AppRoutingModule } from './app-routing.module'; | ||||
| 
 | ||||
| import { File } from '@ionic-native/file/ngx'; | ||||
| 
 | ||||
| @NgModule({ | ||||
|   declarations: [AppComponent], | ||||
|   entryComponents: [], | ||||
|   imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule], | ||||
|   providers: [File, { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }], | ||||
|   bootstrap: [AppComponent], | ||||
| }) | ||||
| export class AppModule {} | ||||
							
								
								
									
										16
									
								
								demos/angular2/ionic.sh
									
									
									
									
									
										Executable file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										16
									
								
								demos/angular2/ionic.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,16 @@ | ||||
| #!/bin/bash | ||||
| if [ ! -e SheetJSIonic ]; then | ||||
| 	ionic start SheetJSIonic blank --type angular --cordova --quiet --no-git --no-link --confirm </dev/null | ||||
| 	cd SheetJSIonic | ||||
| 	ionic cordova platform add browser --confirm </dev/null | ||||
| 	ionic cordova platform add ios --confirm </dev/null | ||||
| 	ionic cordova platform add android --confirm </dev/null | ||||
| 	ionic cordova plugin add cordova-plugin-file </dev/null | ||||
| 	npm install --save @ionic-native/core | ||||
| 	npm install --save @ionic-native/file | ||||
| 	npm install --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz | ||||
| 	cp ../ionic-app.module.ts src/app/app.module.ts | ||||
| 	cd - | ||||
| fi | ||||
| 
 | ||||
| cp ionic.ts SheetJSIonic/src/app/home/home.page.ts | ||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue
	
	Block a user