forked from sheetjs/sheetjs
		
	version bump 0.8.2: ODS and cleanup
- README and example cleanup - basic XLSB and ODS write support - flow typecheck for ODS file Note: xlsx.js flow fails: https://github.com/facebook/flow/issues/380 - exposed jszip compression (fixes #220, closes #284) README issues: | id | author | comment | |-----:|:---------------|:---------------------------------------------| | #202 | @sao93859 | closes #202 | | #211 | @alexanderchan | closes #211 corrected examples | | #327 | @cskaandorp | changed saveAs example to match write tests | | #424 | @dskrvk | added note about s2roa h/t @LeonardoPatignio | | #496 | @jimmywarting | closes #496 adapted rABS examples with rAAS | ODS file format issues: | id | author | comment | |-----:|:---------------|:---------------------------------------------| | #148 | @user4815162342| closes #148 h/t @ziacik | | #166 | @paulproteus | closes #166 rudimentary ODS write support | | #177 | @ziacik | closes #177 | | #179 | @ziacik | closes #179 use JSON when available | | #317 | @ziacik | closes #317 | | #328 | @think01 | closes #328 | | #383 | @mdamt | closes #383 duplicate cells should be copied | | #430 | @RB-Lab | closes #430 | | #546 | @lgodard | closes #546 thanks to other changes |
This commit is contained in:
		
							parent
							
								
									2a756fffcc
								
							
						
					
					
						commit
						86d6a093f0
					
				
							
								
								
									
										17
									
								
								.flowconfig
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										17
									
								
								.flowconfig
									
									
									
									
									
								
							| @ -11,8 +11,21 @@ | ||||
| .*/demo/browser.js | ||||
| .*/shim.js | ||||
| 
 | ||||
| .*/odsbits/.* | ||||
| .*/ods.js | ||||
| .*/xlsx.js | ||||
| .*/xlsxworker.js | ||||
| .*/xlsxworker1.js | ||||
| .*/xlsxworker2.js | ||||
| .*/jszip.js | ||||
| .*/tests/.* | ||||
| 
 | ||||
| .*/xlsx.flow.js | ||||
| [include] | ||||
| xlsx.js | ||||
| xlsxworker.flow.js | ||||
| xlsxworker1.flow.js | ||||
| xlsxworker2.flow.js | ||||
| ods.flow.js | ||||
| .*/bin/.*.njs | ||||
| .*/demo/browser.flow.js | ||||
| 
 | ||||
| @ -23,4 +36,4 @@ misc/flowdeps.js | ||||
| [options] | ||||
| module.file_ext=.js | ||||
| module.file_ext=.njs | ||||
| 
 | ||||
| module.ignore_non_literal_requires=true | ||||
|  | ||||
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -13,8 +13,7 @@ tmp | ||||
| *.xlsb | ||||
| *.xlsm | ||||
| *.xlsx | ||||
| *.xlsm | ||||
| *.xlsb | ||||
| *.ods | ||||
| *.xml | ||||
| *.htm | ||||
| *.html | ||||
|  | ||||
| @ -14,6 +14,7 @@ tmp | ||||
| *.xlsb | ||||
| *.xlsm | ||||
| *.xlsx | ||||
| *.ods | ||||
| *.xml | ||||
| *.htm | ||||
| *.html | ||||
|  | ||||
| @ -5,7 +5,9 @@ node_js: | ||||
|   - "5" | ||||
|   - "4.2" | ||||
|   - "0.12" | ||||
|   - "0.11" | ||||
|   - "0.10" | ||||
|   - "0.9" | ||||
|   - "0.8" | ||||
| before_install: | ||||
|   - "npm install -g npm@next" | ||||
|  | ||||
							
								
								
									
										17
									
								
								Makefile
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										17
									
								
								Makefile
									
									
									
									
									
								
							| @ -11,13 +11,19 @@ ULIB=$(shell echo $(LIB) | tr a-z A-Z) | ||||
| DEPS=$(sort $(wildcard bits/*.js)) | ||||
| TARGET=$(LIB).js | ||||
| FLOWTARGET=$(LIB).flow.js | ||||
| FLOWAUX=$(patsubst %.js,%.flow.js,$(AUXTARGETS)) | ||||
| AUXSCPTS=xlsxworker1.js xlsxworker2.js xlsxworker.js | ||||
| FLOWTGTS=$(TARGET) $(AUXTARGETS) $(AUXSCPTS) | ||||
| 
 | ||||
| ## Main Targets
 | ||||
| 
 | ||||
| .PHONY: all | ||||
| all: $(TARGET) $(AUXTARGETS) ## Build library and auxiliary scripts
 | ||||
| all: $(TARGET) $(AUXTARGETS) $(AUXSCPTS) ## Build library and auxiliary scripts
 | ||||
| 
 | ||||
| $(TARGET): $(DEPS) | ||||
| $(FLOWTGTS): %.js : %.flow.js | ||||
| 	node -e 'process.stdout.write(require("fs").readFileSync("$<","utf8").replace(/^[ \t]*\/\*[:#][^*]*\*\/\s*(\n)?/gm,"").replace(/\/\*[:#][^*]*\*\//gm,""))' > $@ | ||||
| 
 | ||||
| $(FLOWTARGET): $(DEPS) | ||||
| 	cat $^ | tr -d '\15\32' > $@ | ||||
| 
 | ||||
| bits/01_version.js: package.json | ||||
| @ -58,6 +64,8 @@ dist-deps: ods.js ## Copy dependencies for distribution | ||||
| 	cp node_modules/codepage/dist/cpexcel.full.js dist/cpexcel.js | ||||
| 	cp jszip.js dist/jszip.js | ||||
| 	cp ods.js dist/ods.js | ||||
| 	uglifyjs ods.js -o dist/ods.min.js --source-map dist/ods.min.map --preamble "$$(head -n 1 bits/00_header.js)" | ||||
| 	misc/strip_sourcemap.sh dist/ods.min.js | ||||
| 
 | ||||
| bower.json: misc/_bower.json package.json | ||||
| 	cat $< | sed 's/_VERSION_/'`grep version package.json | awk '{gsub(/[^0-9a-z\.-]/,"",$$2); print $$2}'`'/' > $@ | ||||
| @ -69,9 +77,8 @@ aux: $(AUXTARGETS) | ||||
| ods: ods.js | ||||
| 
 | ||||
| ODSDEPS=$(sort $(wildcard odsbits/*.js)) | ||||
| ods.js: $(ODSDEPS) ## Build ODS support library
 | ||||
| ods.flow.js: $(ODSDEPS) ## Build ODS support library
 | ||||
| 	cat $(ODSDEPS) | tr -d '\15\32' > $@ | ||||
| 	cp ods.js dist/ods.js | ||||
| 
 | ||||
| 
 | ||||
| ## Testing
 | ||||
| @ -90,7 +97,7 @@ $(TESTFMT): test_%: | ||||
| ## Code Checking
 | ||||
| 
 | ||||
| .PHONY: lint | ||||
| lint: $(TARGET) ## Run jshint and jscs checks
 | ||||
| lint: $(TARGET) $(AUXTARGETS) ## Run jshint and jscs checks
 | ||||
| 	@jshint --show-non-errors $(TARGET) $(AUXTARGETS) | ||||
| 	@jshint --show-non-errors $(CMDS) | ||||
| 	@jshint --show-non-errors package.json bower.json | ||||
|  | ||||
							
								
								
									
										93
									
								
								README.md
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										93
									
								
								README.md
									
									
									
									
									
								
							| @ -14,14 +14,18 @@ Supported read formats: | ||||
| 
 | ||||
| Supported write formats: | ||||
| 
 | ||||
| - XLSX | ||||
| - Excel 2007+ XML Formats (XLSX/XLSM) | ||||
| - Excel 2007+ Binary Format (XLSB) nodejs only | ||||
| - CSV (and general DSV) | ||||
| - JSON and JS objects (various styles) | ||||
| - OpenDocument Spreadsheet (ODS) | ||||
| 
 | ||||
| Demo: <http://oss.sheetjs.com/js-xlsx> | ||||
| 
 | ||||
| Source: <http://git.io/xlsx> | ||||
| 
 | ||||
| Paid support available through the [reinforcements program](http://sheetjs.com/reinforcements) | ||||
| 
 | ||||
| ## Installation | ||||
| 
 | ||||
| With [npm](https://www.npmjs.org/package/xlsx): | ||||
| @ -53,7 +57,7 @@ circumstances, so they do not ship with the core.  For browser use, they must | ||||
| be included directly: | ||||
| 
 | ||||
| ```html | ||||
| <!-- international support from https://github.com/sheetjs/js-codepage --> | ||||
| <!-- international support from js-codepage --> | ||||
| <script src="dist/cpexcel.js"></script> | ||||
| <!-- ODS support --> | ||||
| <script src="dist/ods.js"></script> | ||||
| @ -116,45 +120,75 @@ oReq.onload = function(e) { | ||||
| oReq.send(); | ||||
| ``` | ||||
| 
 | ||||
| - HTML5 drag-and-drop using readAsBinaryString: | ||||
| - HTML5 drag-and-drop using readAsBinaryString or readAsArrayBuffer: | ||||
|   note: readAsBinaryString and readAsArrayBuffer may not be available in every | ||||
|   browser.  Use dynamic feature tests to determine which method to use. | ||||
| 
 | ||||
| ```js | ||||
| /* processing array buffers, only required for readAsArrayBuffer */ | ||||
| function fixdata(data) { | ||||
| 	var o = "", l = 0, w = 10240; | ||||
| 	for(; l<data.byteLength/w; ++l) o+=String.fromCharCode.apply(null,new Uint8Array(data.slice(l*w,l*w+w))); | ||||
| 	o+=String.fromCharCode.apply(null, new Uint8Array(data.slice(l*w))); | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| var rABS = true; // true: readAsBinaryString ; false: readAsArrayBuffer | ||||
| /* set up drag-and-drop event */ | ||||
| function handleDrop(e) { | ||||
|   e.stopPropagation(); | ||||
|   e.preventDefault(); | ||||
|   var files = e.dataTransfer.files; | ||||
|   var i,f; | ||||
|   for (i = 0, f = files[i]; i != files.length; ++i) { | ||||
|   for (i = 0; i != files.length; ++i) { | ||||
|     f = files[i]; | ||||
|     var reader = new FileReader(); | ||||
|     var name = f.name; | ||||
|     reader.onload = function(e) { | ||||
|       var data = e.target.result; | ||||
| 
 | ||||
|       /* if binary string, read with type 'binary' */ | ||||
|       var workbook = XLSX.read(data, {type: 'binary'}); | ||||
|       var workbook; | ||||
|       if(rABS) { | ||||
|         /* if binary string, read with type 'binary' */ | ||||
|         workbook = XLSX.read(data, {type: 'binary'}); | ||||
|       } else { | ||||
|         /* if array buffer, convert to base64 */ | ||||
|         var arr = fixdata(data); | ||||
|         workbook = XLSX.read(btoa(arr), {type: 'base64'}); | ||||
|       } | ||||
| 
 | ||||
|       /* DO SOMETHING WITH workbook HERE */ | ||||
|     }; | ||||
|     reader.readAsBinaryString(f); | ||||
|     if(rABS) reader.readAsBinaryString(f); | ||||
|     else reader.readAsArrayBuffer(f); | ||||
|   } | ||||
| } | ||||
| drop_dom_element.addEventListener('drop', handleDrop, false); | ||||
| ``` | ||||
| 
 | ||||
| - HTML5 input file element using readAsBinaryString: | ||||
| - HTML5 input file element using readAsBinaryString or readAsArrayBuffer: | ||||
| 
 | ||||
| ```js | ||||
| /* fixdata and rABS are defined in the drag and drop example */ | ||||
| function handleFile(e) { | ||||
|   var files = e.target.files; | ||||
|   var i,f; | ||||
|   for (i = 0, f = files[i]; i != files.length; ++i) { | ||||
|   for (i = 0; i != files.length; ++i) { | ||||
|     f = files[i]; | ||||
|     var reader = new FileReader(); | ||||
|     var name = f.name; | ||||
|     reader.onload = function(e) { | ||||
|       var data = e.target.result; | ||||
| 
 | ||||
|       var workbook = XLSX.read(data, {type: 'binary'}); | ||||
|       var workbook; | ||||
|       if(rABS) { | ||||
|         /* if binary string, read with type 'binary' */ | ||||
|         workbook = XLSX.read(data, {type: 'binary'}); | ||||
|       } else { | ||||
|         /* if array buffer, convert to base64 */ | ||||
|         var arr = fixdata(data); | ||||
|         workbook = XLSX.read(btoa(arr), {type: 'base64'}); | ||||
|       } | ||||
| 
 | ||||
|       /* DO SOMETHING WITH workbook HERE */ | ||||
|     }; | ||||
| @ -164,6 +198,11 @@ function handleFile(e) { | ||||
| input_dom_element.addEventListener('change', handleFile, false); | ||||
| ``` | ||||
| 
 | ||||
| The readAsArrayBuffer form requires some preprocessing: | ||||
| 
 | ||||
| ```js | ||||
| ``` | ||||
| 
 | ||||
| ## Working with the Workbook | ||||
| 
 | ||||
| The full object format is described later in this README. | ||||
| @ -254,7 +293,7 @@ function s2ab(s) { | ||||
| } | ||||
| 
 | ||||
| /* the saveAs call downloads a file on the local machine */ | ||||
| saveAs(new Blob([s2ab(wbout)],{type:""}), "test.xlsx") | ||||
| saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), "test.xlsx"); | ||||
| ``` | ||||
| 
 | ||||
| Complete examples: | ||||
| @ -290,8 +329,11 @@ Utilities are available in the `XLSX.utils` object: | ||||
| Exporting: | ||||
| 
 | ||||
| - `sheet_to_json` converts a workbook object to an array of JSON objects. | ||||
| - `sheet_to_csv` generates delimiter-separated-values output | ||||
| - `sheet_to_formulae` generates a list of the formulae (with value fallbacks) | ||||
|   `sheet_to_row_object_array` is an alias that will be removed in the future. | ||||
| - `sheet_to_csv` generates delimiter-separated-values output. | ||||
| - `sheet_to_formulae` generates a list of the formulae (with value fallbacks). | ||||
| 
 | ||||
| The `sheet_to_*` functions accept a worksheet and an optional options object. | ||||
| 
 | ||||
| Cell and cell address manipulation: | ||||
| 
 | ||||
| @ -371,7 +413,7 @@ Type `d` is the Date type, generated only when the option `cellDates` is passed. | ||||
| Since JSON does not have a natural Date type, parsers are generally expected to | ||||
| store ISO 8601 Date strings like you would get from `date.toISOString()`.  On | ||||
| the other hand, writers and exporters should be able to handle date strings and | ||||
| JS Date objects.  Note that Excel disregards the timezone modifier and treats all | ||||
| JS Date objects.  Note that Excel disregards timezone modifiers and treats all | ||||
| dates in the local timezone.  js-xlsx does not correct for this error. | ||||
| 
 | ||||
| Type `s` is the String type.  `v` should be explicitly stored as a string to | ||||
| @ -395,7 +437,7 @@ Special worksheet keys (accessible as `worksheet[key]`, each starting with `!`): | ||||
|   Functions that handle worksheets should test for the presence of `!ref` field. | ||||
|   If the `!ref` is omitted or is not a valid range, functions are free to treat | ||||
|   the sheet as empty or attempt to guess the range.  The standard utilities that | ||||
|   ship with this library treat sheets as empty (for example, the CSV output is an | ||||
|   ship with this library treat sheets as empty (for example, the CSV output is | ||||
|   empty string). | ||||
| 
 | ||||
|   When reading a worksheet with the `sheetRows` property set, the ref parameter | ||||
| @ -468,9 +510,10 @@ The exported `write` and `writeFile` functions accept an options argument: | ||||
| 
 | ||||
| | Option Name | Default | Description                                          | | ||||
| | :---------- | ------: | :--------------------------------------------------- | | ||||
| | cellDates   | false   | Store dates as type `d` (default is `n`)             | | ||||
| | bookSST     | false   | Generate Shared String Table **                      | | ||||
| | cellDates   | `false` | Store dates as type `d` (default is `n`)             | | ||||
| | bookSST     | `false` | Generate Shared String Table **                      | | ||||
| | bookType    | 'xlsx'  | Type of Workbook ("xlsx" or "xlsm" or "xlsb")        | | ||||
| | compression | `false` | Use file compression for formats with ZIP containers | | ||||
| 
 | ||||
| - `bookSST` is slower and more memory intensive, but has better compatibility | ||||
|   with older versions of iOS Numbers | ||||
| @ -483,7 +526,7 @@ The exported `write` and `writeFile` functions accept an options argument: | ||||
| 
 | ||||
| ## Tested Environments | ||||
| 
 | ||||
|  - NodeJS 0.8, 0.10 (latest release), 0.11.14 (unstable), io.js | ||||
|  - NodeJS 0.8, 0.9, 0.10, 0.11, 0.12, 4.x, 5.x, 6.x, 7.x | ||||
|  - IE 6/7/8/9/10/11 using Base64 mode (IE10/11 using HTML5 mode) | ||||
|  - FF 18 using Base64 or HTML5 mode | ||||
|  - Chrome 24 using Base64 or HTML5 mode | ||||
| @ -491,8 +534,8 @@ The exported `write` and `writeFile` functions accept an options argument: | ||||
| Tests utilize the mocha testing framework.  Travis-CI and Sauce Labs links: | ||||
| 
 | ||||
|  - <https://travis-ci.org/SheetJS/js-xlsx> for XLSX module in nodejs | ||||
|  - <https://travis-ci.org/SheetJS/SheetJS.github.io> for XLS* modules | ||||
|  - <https://saucelabs.com/u/sheetjs> for XLS* modules using Sauce Labs | ||||
|  - <https://travis-ci.org/SheetJS/SheetJS.github.io> for XLS\* modules | ||||
|  - <https://saucelabs.com/u/sheetjs> for XLS\* modules using Sauce Labs | ||||
| 
 | ||||
| ## Test Files | ||||
| 
 | ||||
| @ -537,7 +580,7 @@ version release and should not be committed between versions. | ||||
| ## License | ||||
| 
 | ||||
| Please consult the attached LICENSE file for details.  All rights not explicitly | ||||
| granted by the Apache 2.0 license are reserved by the Original Author. | ||||
| granted by the Apache 2.0 License are reserved by the Original Author. | ||||
| 
 | ||||
| It is the opinion of the Original Author that this code conforms to the terms of | ||||
| the Microsoft Open Specifications Promise, falling under the same terms as | ||||
| @ -573,10 +616,16 @@ Open Document Format for Office Applications Version 1.2 (29 September 2011) | ||||
| 
 | ||||
| ## Badges | ||||
| 
 | ||||
| [](https://saucelabs.com/u/xlsx) | ||||
| 
 | ||||
| [](https://travis-ci.org/SheetJS/js-xlsx) | ||||
| 
 | ||||
| [](https://coveralls.io/r/SheetJS/js-xlsx?branch=master) | ||||
| 
 | ||||
| [](https://github.com/SheetJS/js-xlsx) | ||||
| [](https://npmjs.org/package/xlsx) | ||||
| 
 | ||||
| [](https://david-dm.org/sheetjs/js-xlsx) | ||||
| 
 | ||||
| [](https://ghit.me/repo/sheetjs/js-xlsx) | ||||
| 
 | ||||
| [](https://github.com/SheetJS/js-xlsx) | ||||
|  | ||||
							
								
								
									
										17
									
								
								bin/xlsx.njs
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										17
									
								
								bin/xlsx.njs
									
									
									
									
									
								
							| @ -48,7 +48,7 @@ if(process.version === 'v0.10.31') { | ||||
| 	process.exit(1); | ||||
| } | ||||
| 
 | ||||
| var filename, sheetname = ''; | ||||
| var filename/*:?string*/, sheetname = ''; | ||||
| if(program.args[0]) { | ||||
| 	filename = program.args[0]; | ||||
| 	if(program.args[1]) sheetname = program.args[1]; | ||||
| @ -60,13 +60,13 @@ if(!filename) { | ||||
| 	console.error(n + ": must specify a filename"); | ||||
| 	process.exit(1); | ||||
| } | ||||
| 
 | ||||
| /*:: if(filename) { */ | ||||
| if(!fs.existsSync(filename)) { | ||||
| 	console.error(n + ": " + filename + ": No such file or directory"); | ||||
| 	process.exit(2); | ||||
| } | ||||
| 
 | ||||
| var opts = {}, wb; | ||||
| var opts = {}, wb/*:?Workbook*/; | ||||
| if(program.listSheets) opts.bookSheets = true; | ||||
| if(program.sheetRows) opts.sheetRows = program.sheetRows; | ||||
| if(program.password) opts.password = program.password; | ||||
| @ -98,6 +98,7 @@ else try { | ||||
| } | ||||
| if(program.read) process.exit(0); | ||||
| 
 | ||||
| /*::   if(wb) { */ | ||||
| if(program.listSheets) { | ||||
| 	console.log(wb.SheetNames.join("\n")); | ||||
| 	process.exit(0); | ||||
| @ -105,9 +106,9 @@ if(program.listSheets) { | ||||
| 
 | ||||
| var wopts = {WTF:opts.WTF, bookSST:program.sst}; | ||||
| 
 | ||||
| if(program.xlsx) return X.writeFile(wb, sheetname || (filename + ".xlsx"), wopts); | ||||
| if(program.xlsm) return X.writeFile(wb, sheetname || (filename + ".xlsm"), wopts); | ||||
| if(program.xlsb) return X.writeFile(wb, sheetname || (filename + ".xlsb"), wopts); | ||||
| if(program.xlsx) { X.writeFile(wb, sheetname || (filename + ".xlsx"), wopts); process.exit(0); } | ||||
| if(program.xlsm) { X.writeFile(wb, sheetname || (filename + ".xlsm"), wopts); process.exit(0); } | ||||
| if(program.xlsb) { X.writeFile(wb, sheetname || (filename + ".xlsb"), wopts); process.exit(0); } | ||||
| 
 | ||||
| var target_sheet = sheetname || ''; | ||||
| if(target_sheet === '') target_sheet = wb.SheetNames[0]; | ||||
| @ -121,7 +122,7 @@ try { | ||||
| 	process.exit(4); | ||||
| } | ||||
| 
 | ||||
| if(program.perf) return; | ||||
| if(program.perf) process.exit(0); | ||||
| 
 | ||||
| var oo = ""; | ||||
| if(!program.quiet) console.error(target_sheet); | ||||
| @ -132,3 +133,5 @@ else oo = X.utils.make_csv(ws, {FS:program.fieldSep, RS:program.rowSep}); | ||||
| 
 | ||||
| if(program.output) fs.writeFileSync(program.output, oo); | ||||
| else console.log(oo); | ||||
| /*::   } */ | ||||
| /*:: } */ | ||||
|  | ||||
| @ -1 +1 @@ | ||||
| XLSX.version = '0.8.1'; | ||||
| XLSX.version = '0.8.2'; | ||||
|  | ||||
							
								
								
									
										8
									
								
								bits/09_types.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										8
									
								
								bits/09_types.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| /*:: | ||||
| declare type Block = any; | ||||
| declare type BufArray = { | ||||
| 	next(sz:number):Block; | ||||
| 	end():any; | ||||
| 	push(buf:Block):void; | ||||
| }; | ||||
| */ | ||||
| @ -1,4 +1,4 @@ | ||||
| function isval(x) { return x !== undefined && x !== null; } | ||||
| function isval(x/*:?any*/)/*:boolean*/ { return x !== undefined && x !== null; } | ||||
| 
 | ||||
| function keys(o) { return Object.keys(o); } | ||||
| 
 | ||||
| @ -36,7 +36,7 @@ function datenum(v, date1904) { | ||||
| 	return (epoch + 2209161600000) / (24 * 60 * 60 * 1000); | ||||
| } | ||||
| 
 | ||||
| function cc2str(arr) { | ||||
| function cc2str(arr/*:Array<number>*/)/*:string*/ { | ||||
| 	var o = ""; | ||||
| 	for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]); | ||||
| 	return o; | ||||
|  | ||||
| @ -26,12 +26,13 @@ function getzipfile(zip, file) { | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| function getzipdata(zip, file, safe) { | ||||
| function getzipdata(zip, file, safe/*:?boolean*/) { | ||||
| 	if(!safe) return getdata(getzipfile(zip, file)); | ||||
| 	if(!file) return null; | ||||
| 	try { return getzipdata(zip, file); } catch(e) { return null; } | ||||
| } | ||||
| 
 | ||||
| /*:: declare var JSZip:any; */ | ||||
| var _fs, jszip; | ||||
| if(typeof JSZip !== 'undefined') jszip = JSZip; | ||||
| if (typeof exports !== 'undefined') { | ||||
|  | ||||
| @ -132,7 +132,8 @@ function WriteShift(t, val, f) { | ||||
| 		size = 2 * val.length; | ||||
| 	} else switch(t) { | ||||
| 		case  1: size = 1; this[this.l] = val&255; break; | ||||
| 		case  3: size = 3; this[this.l+2] = val & 255; val >>>= 8; this[this.l+1] = val&255; val >>>= 8; this[this.l] = val&255; break; | ||||
| 		case  2: size = 2; this[this.l] = val&255; val >>>= 8; this[this.l+1] = val&255; break; | ||||
| 		case  3: size = 3; this[this.l] = val&255; val >>>= 8; this[this.l+1] = val&255; val >>>= 8; this[this.l+2] = val&255; break; | ||||
| 		case  4: size = 4; this.writeUInt32LE(val, this.l); break; | ||||
| 		case  8: size = 8; if(f === 'f') { this.writeDoubleLE(val, this.l); break; } | ||||
| 		/* falls through */ | ||||
| @ -148,16 +149,16 @@ function CheckField(hexstr, fld) { | ||||
| 	this.l += hexstr.length>>1; | ||||
| } | ||||
| 
 | ||||
| function prep_blob(blob, pos) { | ||||
| function prep_blob(blob, pos/*:number*/) { | ||||
| 	blob.l = pos; | ||||
| 	blob.read_shift = ReadShift; | ||||
| 	blob.chk = CheckField; | ||||
| 	blob.write_shift = WriteShift; | ||||
| } | ||||
| 
 | ||||
| function parsenoop(blob, length) { blob.l += length; } | ||||
| function parsenoop(blob, length/*:number*/) { blob.l += length; } | ||||
| 
 | ||||
| function writenoop(blob, length) { blob.l += length; } | ||||
| function writenoop(blob, length/*:number*/) { blob.l += length; } | ||||
| 
 | ||||
| function new_buf(sz) { | ||||
| 	var o = new_raw_buf(sz); | ||||
|  | ||||
| @ -26,7 +26,7 @@ function buf_array() { | ||||
| 	var curbuf = newblk(blksz); | ||||
| 
 | ||||
| 	var endbuf = function ba_endbuf() { | ||||
| 		curbuf.length = curbuf.l; | ||||
| 		if(curbuf.length > curbuf.l) curbuf = curbuf.slice(0, curbuf.l); | ||||
| 		if(curbuf.length > 0) bufs.push(curbuf); | ||||
| 		curbuf = null; | ||||
| 	}; | ||||
| @ -47,7 +47,7 @@ function buf_array() { | ||||
| 	return { next:next, push:push, end:end, _bufs:bufs }; | ||||
| } | ||||
| 
 | ||||
| function write_record(ba, type, payload, length) { | ||||
| function write_record(ba/*:BufArray*/, type/*:string*/, payload, length/*:?number*/) { | ||||
| 	var t = evert_RE[type], l; | ||||
| 	if(!length) length = XLSBRecordEnum[t].p || (payload||[]).length || 0; | ||||
| 	l = 1 + (t >= 0x80 ? 1 : 0) + 1 + length; | ||||
| @ -62,5 +62,5 @@ function write_record(ba, type, payload, length) { | ||||
| 		if(length >= 0x80) { o.write_shift(1, (length & 0x7F)+0x80); length >>= 7; } | ||||
| 		else { o.write_shift(1, length); break; } | ||||
| 	} | ||||
| 	if(length > 0 && is_buf(payload)) ba.push(payload); | ||||
| 	if(/*:: length != null &&*/length > 0 && is_buf(payload)) ba.push(payload); | ||||
| } | ||||
|  | ||||
| @ -91,6 +91,15 @@ function parse_RkNumber(data) { | ||||
| 	var RK = fInt === 0 ? __double([0,0,0,0,b[0],b[1],b[2],b[3]],0) : __readInt32LE(b,0)>>2; | ||||
| 	return fX100 ? RK/100 : RK; | ||||
| } | ||||
| function write_RkNumber(data/*:number*/, o) { | ||||
| 	if(o == null) o = new_buf(4); | ||||
| 	var fX100 = 0, fInt = 0, d100 = data * 100; | ||||
| 	if(data == (data | 0) && data >= -(1<<29) && data < (1 << 29)) { fInt = 1; } | ||||
| 	else if(d100 == (d100 | 0) && d100 >= -(1<<29) && d100 < (1 << 29)) { fInt = 1; fX100 = 1; } | ||||
| 	if(fInt) o.write_shift(-4, ((fX100 ? d100 : data) << 2) + (fX100 + 2)); | ||||
| 	else throw new Error("unsupported RkNumber " + data); // TODO
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* [MS-XLSB] 2.5.153 */ | ||||
| function parse_UncheckedRfX(data) { | ||||
| @ -113,8 +122,9 @@ function write_UncheckedRfX(r, o) { | ||||
| 
 | ||||
| /* [MS-XLSB] 2.5.171 */ | ||||
| /* [MS-XLS] 2.5.342 */ | ||||
| /* TODO: error checking, NaN and Infinity values are not valid Xnum */ | ||||
| function parse_Xnum(data, length) { return data.read_shift(8, 'f'); } | ||||
| function write_Xnum(data, o) { return (o || new_buf(8)).write_shift(8, 'f', data); } | ||||
| function write_Xnum(data, o) { return (o || new_buf(8)).write_shift(8, data, 'f'); } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.5.198.2 */ | ||||
| var BErr = { | ||||
|  | ||||
| @ -40,7 +40,7 @@ function parse_cust_props(data, opts) { | ||||
| 						p[name] = unescapexml(text); | ||||
| 						break; | ||||
| 					default: | ||||
| 						if(typeof console !== 'undefined') console.warn('Unexpected', x, type, toks); | ||||
| 						if(opts.WTF && typeof console !== 'undefined') console.warn('Unexpected', x, type, toks); | ||||
| 				} | ||||
| 			} else if(x.substr(0,2) === "</") { | ||||
| 			} else if(opts.WTF) throw new Error(x); | ||||
|  | ||||
| @ -24,7 +24,7 @@ function parse_ws_xml(data, opts, rels) { | ||||
| 	var mergecells = []; | ||||
| 	if(data.indexOf("</mergeCells>")!==-1) { | ||||
| 		var merges = data.match(mergecregex); | ||||
| 		for(ridx = 0; ridx != merges.length; ++ridx) | ||||
| 		if(merges) for(ridx = 0; ridx != merges.length; ++ridx) | ||||
| 			mergecells[ridx] = safe_decode_range(merges[ridx].substr(merges[ridx].indexOf("\"")+1)); | ||||
| 	} | ||||
| 
 | ||||
| @ -36,7 +36,7 @@ function parse_ws_xml(data, opts, rels) { | ||||
| 		parse_ws_xml_cols(columns, cols); | ||||
| 	} | ||||
| 
 | ||||
| 	var refguess = {s: {r:1000000, c:1000000}, e: {r:0, c:0} }; | ||||
| 	var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} }; | ||||
| 
 | ||||
| 	/* 18.3.1.80 sheetData CT_SheetData ? */ | ||||
| 	var mtch=data.match(sheetdataregex); | ||||
| @ -282,7 +282,7 @@ var WS_XML_ROOT = writextag('worksheet', null, { | ||||
| 	'xmlns:r': XMLNS.r | ||||
| }); | ||||
| 
 | ||||
| function write_ws_xml(idx, opts, wb) { | ||||
| function write_ws_xml(idx/*:number*/, opts, wb)/*:string*/ { | ||||
| 	var o = [XML_HEADER, WS_XML_ROOT]; | ||||
| 	var s = wb.SheetNames[idx], sidx = 0, rdata = ""; | ||||
| 	var ws = wb.Sheets[s]; | ||||
|  | ||||
							
								
								
									
										105
									
								
								bits/68_wsbin.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										105
									
								
								bits/68_wsbin.js
									
									
									
									
									
								
							| @ -6,6 +6,45 @@ function parse_BrtRowHdr(data, length) { | ||||
| 	data.l += length-4; | ||||
| 	return z; | ||||
| } | ||||
| function write_BrtRowHdr(R/*:number*/, range, ws) { | ||||
| 	var o = new_buf(17+8*16); | ||||
| 	o.write_shift(4, R); | ||||
| 
 | ||||
| 	/* TODO: flags styles */ | ||||
| 	o.write_shift(4, 0); | ||||
| 	o.write_shift(2, 0x0140); | ||||
| 	o.write_shift(2, 0); | ||||
| 	o.write_shift(1, 0); | ||||
| 
 | ||||
| 	/* [MS-XLSB] 2.5.8 BrtColSpan explains the mechanism */ | ||||
| 	var ncolspan = 0, lcs = o.l; | ||||
| 	o.l += 4; | ||||
| 
 | ||||
| 	var caddr = {r:R, c:0}; | ||||
| 	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; | ||||
| 			if(ws[encode_cell(caddr)]) { if(first < 0) first = j; last = j; } | ||||
| 		} | ||||
| 		if(first < 0) continue; | ||||
| 		++ncolspan; | ||||
| 		o.write_shift(4, first); | ||||
| 		o.write_shift(4, last); | ||||
| 	} | ||||
| 
 | ||||
| 	var l = o.l; | ||||
| 	o.l = lcs; | ||||
| 	o.write_shift(4, ncolspan); | ||||
| 	o.l = l; | ||||
| 
 | ||||
| 	return o.length > o.l ? o.slice(0, o.l) : o; | ||||
| } | ||||
| function write_row_header(ba, ws, range, R) { | ||||
| 	var o = write_BrtRowHdr(R, range, ws); | ||||
| 	if(o.length > 17) write_record(ba, 'BrtRowHdr', o); | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.812 BrtWsDim */ | ||||
| var parse_BrtWsDim = parse_UncheckedRfX; | ||||
| @ -25,9 +64,9 @@ function parse_BrtCellBlank(data, length) { | ||||
| 	var cell = parse_XLSBCell(data); | ||||
| 	return [cell]; | ||||
| } | ||||
| function write_BrtCellBlank(cell, val, o) { | ||||
| function write_BrtCellBlank(cell, ncell, o) { | ||||
| 	if(o == null) o = new_buf(8); | ||||
| 	return write_XLSBCell(val, o); | ||||
| 	return write_XLSBCell(ncell, o); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| @ -37,12 +76,18 @@ function parse_BrtCellBool(data, length) { | ||||
| 	var fBool = data.read_shift(1); | ||||
| 	return [cell, fBool, 'b']; | ||||
| } | ||||
| function write_BrtCellBool(cell, ncell, o) { | ||||
| 	if(o == null) o = new_buf(9); | ||||
| 	write_XLSBCell(ncell, o); | ||||
| 	o.write_shift(1, cell.v ? 1 : 0); | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.305 BrtCellError */ | ||||
| function parse_BrtCellError(data, length) { | ||||
| 	var cell = parse_XLSBCell(data); | ||||
| 	var fBool = data.read_shift(1); | ||||
| 	return [cell, fBool, 'e']; | ||||
| 	var bError = data.read_shift(1); | ||||
| 	return [cell, bError, 'e']; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.308 BrtCellIsst */ | ||||
| @ -51,6 +96,12 @@ function parse_BrtCellIsst(data, length) { | ||||
| 	var isst = data.read_shift(4); | ||||
| 	return [cell, isst, 's']; | ||||
| } | ||||
| function write_BrtCellIsst(cell, ncell, o) { | ||||
| 	if(o == null) o = new_buf(12); | ||||
| 	write_XLSBCell(ncell, o); | ||||
| 	o.write_shift(4, ncell.v); | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.310 BrtCellReal */ | ||||
| function parse_BrtCellReal(data, length) { | ||||
| @ -58,6 +109,12 @@ function parse_BrtCellReal(data, length) { | ||||
| 	var value = parse_Xnum(data); | ||||
| 	return [cell, value, 'n']; | ||||
| } | ||||
| function write_BrtCellReal(cell, ncell, o) { | ||||
| 	if(o == null) o = new_buf(16); | ||||
| 	write_XLSBCell(ncell, o); | ||||
| 	write_Xnum(cell.v, o); | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.311 BrtCellRk */ | ||||
| function parse_BrtCellRk(data, length) { | ||||
| @ -65,6 +122,13 @@ function parse_BrtCellRk(data, length) { | ||||
| 	var value = parse_RkNumber(data); | ||||
| 	return [cell, value, 'n']; | ||||
| } | ||||
| function write_BrtCellRk(cell, ncell, o) { | ||||
| 	if(o == null) o = new_buf(12); | ||||
| 	write_XLSBCell(ncell, o); | ||||
| 	write_RkNumber(cell.v, o); | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.314 BrtCellSt */ | ||||
| function parse_BrtCellSt(data, length) { | ||||
| @ -72,6 +136,12 @@ function parse_BrtCellSt(data, length) { | ||||
| 	var value = parse_XLWideString(data); | ||||
| 	return [cell, value, 'str']; | ||||
| } | ||||
| function write_BrtCellSt(cell, ncell, o) { | ||||
| 	if(o == null) o = new_buf(12 + 4 * cell.v.length); | ||||
| 	write_XLSBCell(ncell, o); | ||||
| 	write_XLWideString(cell.v, o); | ||||
| 	return o.length > o.l ? o.slice(0, o.l) : o; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.647 BrtFmlaBool */ | ||||
| function parse_BrtFmlaBool(data, length, opts) { | ||||
| @ -147,12 +217,13 @@ function parse_ws_bin(data, opts, rels) { | ||||
| 	var s = {}; | ||||
| 
 | ||||
| 	var ref; | ||||
| 	var refguess = {s: {r:1000000, c:1000000}, e: {r:0, c:0} }; | ||||
| 	var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} }; | ||||
| 
 | ||||
| 	var pass = false, end = false; | ||||
| 	var row, p, cf, R, C, addr, sstr, rr; | ||||
| 	var mergecells = []; | ||||
| 	recordhopper(data, function ws_parse(val, R) { | ||||
| 		//console.log(R);
 | ||||
| 		if(end) return; | ||||
| 		switch(R.n) { | ||||
| 			case 'BrtWsDim': ref = val; break; | ||||
| @ -329,7 +400,7 @@ function parse_ws_bin(data, opts, rels) { | ||||
| 			default: if(!pass || opts.WTF) throw new Error("Unexpected record " + R.n); | ||||
| 		} | ||||
| 	}, opts); | ||||
| 	if(!s["!ref"] && (refguess.s.r < 1000000 || ref.e.r > 0 || ref.e.c > 0 || ref.s.r > 0 || ref.s.c > 0)) s["!ref"] = encode_range(ref); | ||||
| 	if(!s["!ref"] && (refguess.s.r < 2000000 || ref.e.r > 0 || ref.e.c > 0 || ref.s.r > 0 || ref.s.c > 0)) s["!ref"] = encode_range(ref); | ||||
| 	if(opts.sheetRows && s["!ref"]) { | ||||
| 		var tmpref = safe_decode_range(s["!ref"]); | ||||
| 		if(opts.sheetRows < +tmpref.e.r) { | ||||
| @ -362,12 +433,23 @@ function write_ws_bin_cell(ba, cell, R, C, opts) { | ||||
| 		case 's': case 'str': | ||||
| 			if(opts.bookSST) { | ||||
| 				vv = get_sst_id(opts.Strings, cell.v); | ||||
| 				o.t = "s"; break; | ||||
| 				o.t = "s"; o.v = vv; | ||||
| 				write_record(ba, "BrtCellIsst", write_BrtCellIsst(cell, o)); | ||||
| 			} else { | ||||
| 				o.t = "str"; | ||||
| 				write_record(ba, "BrtCellSt", write_BrtCellSt(cell, o)); | ||||
| 			} | ||||
| 			o.t = "str"; break; | ||||
| 		case 'n': break; | ||||
| 		case 'b': o.t = "b"; break; | ||||
| 		case 'e': o.t = "e"; break; | ||||
| 			return; | ||||
| 		case 'n': | ||||
| 			/* TODO: determine threshold for Real vs RK */ | ||||
| 			if(cell.v == (cell.v | 0) && cell.v > -1000 && cell.v < 1000) write_record(ba, "BrtCellRk", write_BrtCellRk(cell, o)); | ||||
| 			else write_record(ba, "BrtCellReal", write_BrtCellReal(cell, o)); | ||||
| 			return; | ||||
| 		case 'b': | ||||
| 			o.t = "b"; | ||||
| 			write_record(ba, "BrtCellBool", write_BrtCellBool(cell, o)); | ||||
| 			return; | ||||
| 		case 'e': /* TODO: error */ o.t = "e"; break; | ||||
| 	} | ||||
| 	write_record(ba, "BrtCellBlank", write_BrtCellBlank(cell, o)); | ||||
| } | ||||
| @ -379,6 +461,7 @@ function write_CELLTABLE(ba, ws, idx, opts, wb) { | ||||
| 		rr = encode_row(R); | ||||
| 		/* [ACCELLTABLE] */ | ||||
| 		/* BrtRowHdr */ | ||||
| 		write_row_header(ba, ws, range, R); | ||||
| 		for(var C = range.s.c; C <= range.e.c; ++C) { | ||||
| 			/* *16384CELL */ | ||||
| 			if(R === range.s.r) cols[C] = encode_col(C); | ||||
|  | ||||
| @ -13,7 +13,7 @@ function write_BrtBundleSh(data, o) { | ||||
| 	o.write_shift(4, data.iTabID); | ||||
| 	write_RelID(data.strRelID, o); | ||||
| 	write_XLWideString(data.name.substr(0,31), o); | ||||
| 	return o; | ||||
| 	return o.length > o.l ? o.slice(0, o.l) : o; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.807 BrtWbProp */ | ||||
| @ -121,7 +121,7 @@ function write_BrtFileVersion(data, o) { | ||||
| 	write_XLWideString(XLSX.version, o); | ||||
| 	write_XLWideString("7262", o); | ||||
| 	o.length = o.l; | ||||
| 	return o; | ||||
| 	return o.length > o.l ? o.slice(0, o.l) : o; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.1.7.60 Workbook */ | ||||
| @ -144,6 +144,7 @@ function write_BrtCalcProp(data, o) { | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.640 BrtFileRecover */ | ||||
| function write_BrtFileRecover(data, o) { | ||||
| 	if(!o) o = new_buf(1); | ||||
| 	o.write_shift(1,0); | ||||
| @ -156,22 +157,22 @@ function write_wb_bin(wb, opts) { | ||||
| 	write_record(ba, "BrtBeginBook"); | ||||
| 	write_record(ba, "BrtFileVersion", write_BrtFileVersion()); | ||||
| 	/* [[BrtFileSharingIso] BrtFileSharing] */ | ||||
| 	write_record(ba, "BrtWbProp", write_BrtWbProp()); | ||||
| 	if(0) write_record(ba, "BrtWbProp", write_BrtWbProp()); | ||||
| 	/* [ACABSPATH] */ | ||||
| 	/* [[BrtBookProtectionIso] BrtBookProtection] */ | ||||
| 	write_BOOKVIEWS(ba, wb, opts); | ||||
| 	if(0) write_BOOKVIEWS(ba, wb, opts); | ||||
| 	write_BUNDLESHS(ba, wb, opts); | ||||
| 	/* [FNGROUP] */ | ||||
| 	/* [EXTERNALS] */ | ||||
| 	/* *BrtName */ | ||||
| 	write_record(ba, "BrtCalcProp", write_BrtCalcProp()); | ||||
| 	if(0) write_record(ba, "BrtCalcProp", write_BrtCalcProp()); | ||||
| 	/* [BrtOleSize] */ | ||||
| 	/* *(BrtUserBookView *FRT) */ | ||||
| 	/* [PIVOTCACHEIDS] */ | ||||
| 	/* [BrtWbFactoid] */ | ||||
| 	/* [SMARTTAGTYPES] */ | ||||
| 	/* [BrtWebOpt] */ | ||||
| 	write_record(ba, "BrtFileRecover", write_BrtFileRecover()); | ||||
| 	if(0) write_record(ba, "BrtFileRecover", write_BrtFileRecover()); | ||||
| 	/* [WEBPUBITEMS] */ | ||||
| 	/* [CRERRS] */ | ||||
| 	/* FRTWORKBOOK */ | ||||
|  | ||||
| @ -147,7 +147,7 @@ function parse_xlml_xml(d, opts) { | ||||
| 	var sheets = {}, sheetnames = [], cursheet = {}, sheetname = ""; | ||||
| 	var table = {}, cell = {}, row = {}, dtag, didx; | ||||
| 	var c = 0, r = 0; | ||||
| 	var refguess = {s: {r:1000000, c:1000000}, e: {r:0, c:0} }; | ||||
| 	var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} }; | ||||
| 	var styles = {}, stag = {}; | ||||
| 	var ss = "", fidx = 0; | ||||
| 	var mergecells = []; | ||||
| @ -207,7 +207,7 @@ function parse_xlml_xml(d, opts) { | ||||
| 				if(mergecells.length) cursheet["!merges"] = mergecells; | ||||
| 				sheets[sheetname] = cursheet; | ||||
| 			} else { | ||||
| 				refguess = {s: {r:1000000, c:1000000}, e: {r:0, c:0} }; | ||||
| 				refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} }; | ||||
| 				r = c = 0; | ||||
| 				state.push([Rn[3], false]); | ||||
| 				tmp = xlml_parsexmltag(Rn[0]); | ||||
|  | ||||
							
								
								
									
										11
									
								
								bits/83_ods.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										11
									
								
								bits/83_ods.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| /* Helper functions to call out to ODS */ | ||||
| function parse_ods(zip, opts) { | ||||
| 	if(typeof module !== "undefined" && typeof require !== 'undefined' && typeof ODS === 'undefined') ODS = require('./od' + 's'); | ||||
| 	if(typeof ODS === 'undefined' || !ODS.parse_ods) throw new Error("Unsupported ODS"); | ||||
| 	return ODS.parse_ods(zip, opts); | ||||
| } | ||||
| function write_ods(wb, opts) { | ||||
| 	if(typeof module !== "undefined" && typeof require !== 'undefined' && typeof ODS === 'undefined') ODS = require('./od' + 's'); | ||||
| 	if(typeof ODS === 'undefined' || !ODS.write_ods) throw new Error("Unsupported ODS"); | ||||
| 	return ODS.write_ods(wb, opts); | ||||
| } | ||||
| @ -1,6 +0,0 @@ | ||||
| /* Helper function to call out to ODS parser */ | ||||
| function parse_ods(zip, opts) { | ||||
| 	if(typeof module !== "undefined" && typeof require !== 'undefined' && typeof ODS === 'undefined') ODS = require('./od' + 's'); | ||||
| 	if(typeof ODS === 'undefined' || !ODS.parse_ods) throw new Error("Unsupported ODS"); | ||||
| 	return ODS.parse_ods(zip, opts); | ||||
| } | ||||
| @ -36,5 +36,7 @@ var fix_write_opts = fix_opts_func([ | ||||
| 
 | ||||
| 	['bookType', 'xlsx'], /* Type of workbook (xlsx/m/b) */ | ||||
| 
 | ||||
| 	['compression', false], /* Use file compression */ | ||||
| 
 | ||||
| 	['WTF', false] /* WTF mode (throws errors) */ | ||||
| ]); | ||||
|  | ||||
| @ -10,6 +10,7 @@ function add_rels(rels, rId, f, type, relobj) { | ||||
| } | ||||
| 
 | ||||
| function write_zip(wb, opts) { | ||||
| 	if(opts.bookType == "ods") return write_ods(wb, opts); | ||||
| 	if(wb && !wb.SSF) { | ||||
| 		wb.SSF = SSF.get_table(); | ||||
| 	} | ||||
|  | ||||
| @ -1,13 +1,17 @@ | ||||
| function write_zip_type(wb, opts) { | ||||
| 	var o = opts||{}; | ||||
| 	var z = write_zip(wb, o); | ||||
| 	var oopts = {}; | ||||
| 	if(opts.compression) oopts.compression = 'DEFLATE'; | ||||
| 	switch(o.type) { | ||||
| 		case "base64": return z.generate({type:"base64"}); | ||||
| 		case "binary": return z.generate({type:"string"}); | ||||
| 		case "buffer": return z.generate({type:"nodebuffer"}); | ||||
| 		case "file": return _fs.writeFileSync(o.file, z.generate({type:"nodebuffer"})); | ||||
| 		case "base64": oopts.type = "base64"; break; | ||||
| 		case "binary": oopts.type = "string"; break; | ||||
| 		case "buffer": | ||||
| 		case "file": oopts.type = "nodebuffer"; break; | ||||
| 		default: throw new Error("Unrecognized type " + o.type); | ||||
| 	} | ||||
| 	if(o.type === "file") return _fs.writeFileSync(o.file, z.generate(oopts)); | ||||
| 	return z.generate(oopts); | ||||
| } | ||||
| 
 | ||||
| function writeSync(wb, opts) { | ||||
| @ -21,13 +25,14 @@ function writeSync(wb, opts) { | ||||
| function writeFileSync(wb, filename, opts) { | ||||
| 	var o = opts||{}; o.type = 'file'; | ||||
| 	o.file = filename; | ||||
| 	switch(o.file.substr(-5).toLowerCase()) { | ||||
| 	if(!o.bookType) switch(o.file.substr(-5).toLowerCase()) { | ||||
| 		case '.xlsx': o.bookType = 'xlsx'; break; | ||||
| 		case '.xlsm': o.bookType = 'xlsm'; break; | ||||
| 		case '.xlsb': o.bookType = 'xlsb'; break; | ||||
| 	default: switch(o.file.substr(-4).toLowerCase()) { | ||||
| 		case '.xls': o.bookType = 'xls'; break; | ||||
| 		case '.xml': o.bookType = 'xml'; break; | ||||
| 		case '.ods': o.bookType = 'ods'; break; | ||||
| 	}} | ||||
| 	return writeSync(wb, o); | ||||
| } | ||||
|  | ||||
| @ -2,7 +2,7 @@ | ||||
|   "name": "js-xlsx", | ||||
|   "homepage": "https://github.com/SheetJS/js-xlsx", | ||||
|   "main": "dist/xlsx.js", | ||||
|   "version": "0.8.1", | ||||
|   "version": "0.8.2", | ||||
|   "ignore": [ | ||||
|     "bin", | ||||
|     "bits", | ||||
|  | ||||
							
								
								
									
										287
									
								
								dist/ods.js
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										287
									
								
								dist/ods.js
									
									
									
									
										vendored
									
									
								
							| @ -21,6 +21,14 @@ function cc2str(arr) { | ||||
| 	for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]); | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| function dup(o) { | ||||
| 	if(typeof JSON != 'undefined') return JSON.parse(JSON.stringify(o)); | ||||
| 	if(typeof o != 'object' || !o) return o; | ||||
| 	var out = {}; | ||||
| 	for(var k in o) if(o.hasOwnProperty(k)) out[k] = dup(o[k]); | ||||
| 	return out; | ||||
| } | ||||
| function getdata(data) { | ||||
| 	if(!data) return null; | ||||
| 	if(data.data) return data.data; | ||||
| @ -67,7 +75,7 @@ function parsexmltag(tag, skip_root) { | ||||
| 	for(; eq !== tag.length; ++eq) if((c = tag.charCodeAt(eq)) === 32 || c === 10 || c === 13) break; | ||||
| 	if(!skip_root) z[0] = tag.substr(0, eq); | ||||
| 	if(eq === tag.length) return z; | ||||
| 	var m = tag.match(attregexg), j=0, w="", v="", i=0, q="", cc=""; | ||||
| 	var m = tag.match(attregexg), j=0, v="", i=0, q="", cc=""; | ||||
| 	if(m) for(i = 0; i != m.length; ++i) { | ||||
| 		cc = m[i]; | ||||
| 		for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break; | ||||
| @ -108,7 +116,7 @@ function escapexml(text){ | ||||
| 	return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).substr(-4) + "_";}); | ||||
| } | ||||
| 
 | ||||
| function parsexmlbool(value, tag) { | ||||
| function parsexmlbool(value) { | ||||
| 	switch(value) { | ||||
| 		case '1': case 'true': case 'TRUE': return true; | ||||
| 		/* case '0': case 'false': case 'FALSE':*/ | ||||
| @ -147,6 +155,8 @@ function parse_isodur(s) { | ||||
| 	} | ||||
| 	return sec; | ||||
| } | ||||
| 
 | ||||
| var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n'; | ||||
| /* copied from js-xls (C) SheetJS Apache2 license */ | ||||
| function xlml_normalize(d) { | ||||
| 	if(has_buf && Buffer.isBuffer(d)) return d.toString('utf8'); | ||||
| @ -157,14 +167,14 @@ function xlml_normalize(d) { | ||||
| var xlmlregex = /<(\/?)([a-z0-9]*:|)([\w-]+)[^>]*>/mg; | ||||
| /* Part 3 Section 4 Manifest File */ | ||||
| var CT_ODS = "application/vnd.oasis.opendocument.spreadsheet"; | ||||
| var parse_manifest = function(d, opts) { | ||||
| function parse_manifest(d, opts) { | ||||
| 	var str = xlml_normalize(d); | ||||
| 	var Rn; | ||||
| 	var FEtag; | ||||
| 	while((Rn = xlmlregex.exec(str))) switch(Rn[3]) { | ||||
| 		case 'manifest': break; // 4.2 <manifest:manifest>
 | ||||
| 		case 'file-entry': // 4.3 <manifest:file-entry>
 | ||||
| 			FEtag = parsexmltag(Rn[0]); | ||||
| 			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>
 | ||||
| @ -172,11 +182,46 @@ var parse_manifest = function(d, opts) { | ||||
| 		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: throw Rn; | ||||
| 		default: if(opts && opts.WTF) throw Rn; | ||||
| 	} | ||||
| }; | ||||
| } | ||||
| 
 | ||||
| function write_manifest(manifest, opts) { | ||||
| 	var o = [XML_HEADER]; | ||||
| 	o.push('<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2">\n'); | ||||
| 	o.push('  <manifest:file-entry manifest:full-path="/" manifest:version="1.2" manifest:media-type="application/vnd.oasis.opendocument.spreadsheet"/>\n'); | ||||
| 	for(var i = 0; i < manifest.length; ++i) o.push('  <manifest:file-entry manifest:full-path="' + manifest[i][0] + '" manifest:media-type="' + manifest[i][1] + '"/>\n'); | ||||
| 	o.push('</manifest:manifest>'); | ||||
| 	return o.join(""); | ||||
| } | ||||
| /* Part 3 Section 6 Metadata Manifest File */ | ||||
| function write_rdf_type(file, res, tag) { | ||||
| 	return [ | ||||
| 		'  <rdf:Description rdf:about="' + file + '">\n', | ||||
| 		'    <rdf:type rdf:resource="http://docs.oasis-open.org/ns/office/1.2/meta/' + (tag || "odf") + '#' + res + '"/>\n', | ||||
| 		'  </rdf:Description>\n' | ||||
| 	].join(""); | ||||
| } | ||||
| function write_rdf_has(base, file) { | ||||
| 	return [ | ||||
| 		'  <rdf:Description rdf:about="' + base + '">\n', | ||||
| 		'    <ns0:hasPart xmlns:ns0="http://docs.oasis-open.org/ns/office/1.2/meta/pkg#" rdf:resource="' + file + '"/>\n', | ||||
| 		'  </rdf:Description>\n' | ||||
| 	].join(""); | ||||
| } | ||||
| function write_rdf(rdf, opts) { | ||||
| 	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 parse_text_p = function(text, tag) { | ||||
| 	return utf8read(text.replace(/<text:s\/>/g," ").replace(/<[^>]*>/g,"")); | ||||
| 	return unescapexml(utf8read(text.replace(/<text:s\/>/g," ").replace(/<[^>]*>/g,""))); | ||||
| }; | ||||
| 
 | ||||
| var utf8read = function utf8reada(orig) { | ||||
| @ -213,27 +258,29 @@ var parse_content_xml = (function() { | ||||
| 		var str = xlml_normalize(d); | ||||
| 		var state = [], tmp; | ||||
| 		var tag; | ||||
| 		var NFtag, NF, pidx; | ||||
| 		var NFtag = {name:""}, NF = "", pidx = 0; | ||||
| 		var sheetag; | ||||
| 		var Sheets = {}, SheetNames = [], ws = {}; | ||||
| 		var Rn, q; | ||||
| 		var ctag; | ||||
| 		var textp, textpidx, textptag; | ||||
| 		var R, C, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}}; | ||||
| 		var ctag = {value:""}; | ||||
| 		var textp = "", textpidx = 0, textptag; | ||||
| 		var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}}; | ||||
| 		var number_format_map = {}; | ||||
| 		var merges = [], mrange = {}, mR = 0, mC = 0; | ||||
| 
 | ||||
| 		var rept = 1; | ||||
| 		xlmlregex.lastIndex = 0; | ||||
| 		while((Rn = xlmlregex.exec(str))) switch(Rn[3]) { | ||||
| 
 | ||||
| 			case 'table': // 9.1.2 <table:table>
 | ||||
| 				if(Rn[1]==='/') { | ||||
| 					if(range.e.c >= range.s.c && range.e.r >= range.s.r) ws['!ref'] = get_utils().encode_range(range); | ||||
| 					if(merges.length) ws['!merges'] = merges; | ||||
| 					sheetag.name = utf8read(sheetag.name); | ||||
| 					SheetNames.push(sheetag.name); | ||||
| 					Sheets[sheetag.name] = ws; | ||||
| 				} | ||||
| 				else if(Rn[0].charAt(Rn[0].length-2) !== '/') { | ||||
| 					sheetag = parsexmltag(Rn[0]); | ||||
| 					sheetag = parsexmltag(Rn[0], false); | ||||
| 					R = C = -1; | ||||
| 					range.s.r = range.s.c = 10000000; range.e.r = range.e.c = 0; | ||||
| 					ws = {}; merges = []; | ||||
| @ -247,17 +294,18 @@ var parse_content_xml = (function() { | ||||
| 				++C; break; /* stub */ | ||||
| 			case 'table-cell': | ||||
| 				if(Rn[0].charAt(Rn[0].length-2) === '/') { | ||||
| 					ctag = parsexmltag(Rn[0]); | ||||
| 					ctag = parsexmltag(Rn[0], false); | ||||
| 					if(ctag['number-columns-repeated']) C+= parseInt(ctag['number-columns-repeated'], 10); | ||||
| 					else ++C; | ||||
| 				} | ||||
| 				else if(Rn[1]!=='/') { | ||||
| 					++C; | ||||
| 					rept = 1; | ||||
| 					if(C > range.e.c) range.e.c = C; | ||||
| 					if(R > range.e.r) range.e.r = R; | ||||
| 					if(C < range.s.c) range.s.c = C; | ||||
| 					if(R < range.s.r) range.s.r = R; | ||||
| 					ctag = parsexmltag(Rn[0]); | ||||
| 					ctag = parsexmltag(Rn[0], false); | ||||
| 					q = {t:ctag['value-type'], v:null}; | ||||
| 					if(ctag['number-columns-spanned'] || ctag['number-rows-spanned']) { | ||||
| 						mR = parseInt(ctag['number-rows-spanned'],10) || 0; | ||||
| @ -265,6 +313,10 @@ var parse_content_xml = (function() { | ||||
| 						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']) rept = parseInt(ctag['number-columns-repeated'], 10); | ||||
| 
 | ||||
| 					/* 19.385 office:value-type */ | ||||
| 					switch(q.t) { | ||||
| 						case 'boolean': q.t = 'b'; q.v = parsexmlbool(ctag['boolean-value']); break; | ||||
| @ -273,14 +325,22 @@ var parse_content_xml = (function() { | ||||
| 						case 'currency': q.t = 'n'; q.v = parseFloat(ctag.value); break; | ||||
| 						case 'date': q.t = 'n'; q.v = datenum(ctag['date-value']); q.z = 'm/d/yy'; break; | ||||
| 						case 'time': q.t = 'n'; q.v = parse_isodur(ctag['time-value'])/86400; break; | ||||
| 						case 'string': q.t = 's'; break; | ||||
| 						default: throw new Error('Unsupported value type ' + q.t); | ||||
| 						default: | ||||
| 							if(q.t === 'string' || !q.t) { | ||||
| 								q.t = 's'; | ||||
| 								if(ctag['string-value'] != null) textp = ctag['string-value']; | ||||
| 							} else throw new Error('Unsupported value type ' + q.t); | ||||
| 					} | ||||
| 				} else { | ||||
| 					if(q.t === 's') q.v = textp; | ||||
| 					if(q.t === 's') q.v = textp || ''; | ||||
| 					if(textp) q.w = textp; | ||||
| 					if(!(opts.sheetRows && opts.sheetRows < R)) ws[get_utils().encode_cell({r:R,c:C})] = q; | ||||
| 					q = null; | ||||
| 					if(!(opts.sheetRows && opts.sheetRows < R)) { | ||||
| 						ws[get_utils().encode_cell({r:R,c:C})] = q; | ||||
| 						while(--rept > 0) ws[get_utils().encode_cell({r:R,c:++C})] = dup(q); | ||||
| 						if(range.e.c <= C) range.e.c = C; | ||||
| 					} | ||||
| 					q = {}; | ||||
| 					textp = ""; | ||||
| 				} | ||||
| 				break; // 9.1.4 <table:table-cell>
 | ||||
| 
 | ||||
| @ -296,6 +356,13 @@ var parse_content_xml = (function() { | ||||
| 			/* ignore state */ | ||||
| 			case 'shapes': // 9.2.8 <table:shapes>
 | ||||
| 			case 'frame': // 10.4.2 <draw:frame>
 | ||||
| 			case 'text-box': // 10.4.3 <draw:text-box>
 | ||||
| 			case 'image': // 10.4.4 <draw:image>
 | ||||
| 			case 'data-pilot-tables': // 9.6.2 <table:data-pilot-tables>
 | ||||
| 			case 'list-style': // 16.30 <text:list-style>
 | ||||
| 			case 'form': // 13.13 <form:form>
 | ||||
| 			case 'dde-links': // 9.8 <table:dde-links>
 | ||||
| 			case 'annotation': // 14.1 <office:annotation>
 | ||||
| 				if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;} | ||||
| 				else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], false]); | ||||
| 				break; | ||||
| @ -309,7 +376,7 @@ var parse_content_xml = (function() { | ||||
| 					if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp; | ||||
| 				} else if(Rn[0].charAt(Rn[0].length-2) !== '/') { | ||||
| 					NF = ""; | ||||
| 					NFtag = parsexmltag(Rn[0]); | ||||
| 					NFtag = parsexmltag(Rn[0], false); | ||||
| 					state.push([Rn[3], true]); | ||||
| 				} break; | ||||
| 
 | ||||
| @ -317,6 +384,7 @@ var parse_content_xml = (function() { | ||||
| 			case 'automatic-styles': break; // 3.15.3 <office:automatic-styles>
 | ||||
| 
 | ||||
| 			case 'style': break; // 16.2 <style:style>
 | ||||
| 			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>
 | ||||
| @ -329,10 +397,12 @@ var parse_content_xml = (function() { | ||||
| 				switch(state[state.length-1][0]) { | ||||
| 					case 'time-style': | ||||
| 					case 'date-style': | ||||
| 						tag = parsexmltag(Rn[0]); | ||||
| 						tag = parsexmltag(Rn[0], false); | ||||
| 						NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break; | ||||
| 				} break; | ||||
| 
 | ||||
| 			case 'fraction': break; // TODO 16.27.6 <number:fraction>
 | ||||
| 
 | ||||
| 			case 'day': // 16.27.11 <number:day>
 | ||||
| 			case 'month': // 16.27.12 <number:month>
 | ||||
| 			case 'year': // 16.27.13 <number:year>
 | ||||
| @ -347,7 +417,7 @@ var parse_content_xml = (function() { | ||||
| 				switch(state[state.length-1][0]) { | ||||
| 					case 'time-style': | ||||
| 					case 'date-style': | ||||
| 						tag = parsexmltag(Rn[0]); | ||||
| 						tag = parsexmltag(Rn[0], false); | ||||
| 						NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break; | ||||
| 				} break; | ||||
| 
 | ||||
| @ -373,30 +443,114 @@ var parse_content_xml = (function() { | ||||
| 			case 'forms': break; // 12.25.2 13.2
 | ||||
| 			case 'table-column': break; // 9.1.6 <table:table-column>
 | ||||
| 
 | ||||
| 			case 'graphic-properties': break; | ||||
| 			case 'null-date': break; // 9.4.2 <table:null-date> TODO: date1904
 | ||||
| 
 | ||||
| 			case 'graphic-properties': break; // 17.21 <style:graphic-properties>
 | ||||
| 			case 'calculation-settings': break; // 9.4.1 <table:calculation-settings>
 | ||||
| 			case 'named-expressions': break; // 9.4.11 <table:named-expressions>
 | ||||
| 			case 'named-range': break; // 9.4.11 <table:named-range>
 | ||||
| 			case 'named-range': break; // 9.4.12 <table:named-range>
 | ||||
| 			case 'named-expression': break; // 9.4.13 <table:named-expression>
 | ||||
| 			case 'sort': break; // 9.4.19 <table:sort>
 | ||||
| 			case 'sort-by': break; // 9.4.20 <table:sort-by>
 | ||||
| 			case 'sort-groups': break; // 9.4.22 <table:sort-groups>
 | ||||
| 
 | ||||
| 			case 'span': break; // <text:span>
 | ||||
| 			case 'line-break': break; // 6.1.5 <text:line-break>
 | ||||
| 			case 'p': | ||||
| 				if(Rn[1]==='/') textp = parse_text_p(str.slice(textpidx,Rn.index), textptag); | ||||
| 				else { textptag = parsexmltag(Rn[0]); textpidx = Rn.index + Rn[0].length; } | ||||
| 				else { textptag = parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; } | ||||
| 				break; // <text:p>
 | ||||
| 			case 's': break; // <text:s>
 | ||||
| 			case 'date': break; // <*:date>
 | ||||
| 			case 'annotation': break; | ||||
| 
 | ||||
| 			case 'object': break; // 10.4.6.2 <draw:object>
 | ||||
| 			case 'title': break; // <*:title>
 | ||||
| 			case 'desc': break; // <*:desc>
 | ||||
| 
 | ||||
| 			case 'table-source': break; // 9.2.6
 | ||||
| 
 | ||||
| 			case 'iteration': break; // 9.4.3 <table:iteration>
 | ||||
| 			case 'content-validations': break; // 9.4.4 <table:
 | ||||
| 			case 'content-validation': break; // 9.4.5 <table:
 | ||||
| 			case 'error-message': break; // 9.4.7 <table:
 | ||||
| 			case 'database-ranges': break; // 9.4.14 <table:database-ranges>
 | ||||
| 			case 'database-range': break; // 9.4.15 <table:database-range>
 | ||||
| 			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>
 | ||||
| 			default: if(opts.WTF) throw Rn; | ||||
| 
 | ||||
| 			case 'list-level-style-bullet': break; // 16.31 <text:
 | ||||
| 			case 'list-level-style-number': break; // 16.32 <text:
 | ||||
| 			case 'list-level-properties': break; // 17.19 <style:
 | ||||
| 
 | ||||
| 			/* 7.3 Document Fields */ | ||||
| 			case 'sender-firstname': // 7.3.6.2
 | ||||
| 			case 'sender-lastname': // 7.3.6.3
 | ||||
| 			case 'sender-initials': // 7.3.6.4
 | ||||
| 			case 'sender-title': // 7.3.6.5
 | ||||
| 			case 'sender-position': // 7.3.6.6
 | ||||
| 			case 'sender-email': // 7.3.6.7
 | ||||
| 			case 'sender-phone-private': // 7.3.6.8
 | ||||
| 			case 'sender-fax': // 7.3.6.9
 | ||||
| 			case 'sender-company': // 7.3.6.10
 | ||||
| 			case 'sender-phone-work': // 7.3.6.11
 | ||||
| 			case 'sender-street': // 7.3.6.12
 | ||||
| 			case 'sender-city': // 7.3.6.13
 | ||||
| 			case 'sender-postal-code': // 7.3.6.14
 | ||||
| 			case 'sender-country': // 7.3.6.15
 | ||||
| 			case 'sender-state-or-province': // 7.3.6.16
 | ||||
| 			case 'author-name': // 7.3.7.1
 | ||||
| 			case 'author-initials': // 7.3.7.2
 | ||||
| 			case 'chapter': // 7.3.8
 | ||||
| 			case 'file-name': // 7.3.9
 | ||||
| 			case 'template-name': // 7.3.9
 | ||||
| 			case 'sheet-name': // 7.3.9
 | ||||
| 				break; | ||||
| 
 | ||||
| 			/* 9.6 Data Pilot Tables <table: */ | ||||
| 			case 'data-pilot-table': // 9.6.3
 | ||||
| 			case 'source-cell-range': // 9.6.5
 | ||||
| 			case 'source-service': // 9.6.6
 | ||||
| 			case 'data-pilot-field': // 9.6.7
 | ||||
| 			case 'data-pilot-level': // 9.6.8
 | ||||
| 			case 'data-pilot-subtotals': // 9.6.9
 | ||||
| 			case 'data-pilot-subtotal': // 9.6.10
 | ||||
| 			case 'data-pilot-members': // 9.6.11
 | ||||
| 			case 'data-pilot-member': // 9.6.12
 | ||||
| 			case 'data-pilot-display-info': // 9.6.13
 | ||||
| 			case 'data-pilot-sort-info': // 9.6.14
 | ||||
| 			case 'data-pilot-layout-info': // 9.6.15
 | ||||
| 			case 'data-pilot-field-reference': // 9.6.16
 | ||||
| 			case 'data-pilot-groups': // 9.6.17
 | ||||
| 			case 'data-pilot-group': // 9.6.18
 | ||||
| 			case 'data-pilot-group-member': // 9.6.19
 | ||||
| 				break; | ||||
| 
 | ||||
| 			/* 10.3 Drawing Shapes */ | ||||
| 			case 'rect': // 10.3.2
 | ||||
| 				break; | ||||
| 
 | ||||
| 			/* 14.6 DDE Connections */ | ||||
| 			case 'dde-connection-decls': // 14.6.2 <text:
 | ||||
| 			case 'dde-connection-decl': // 14.6.3 <text:
 | ||||
| 			case 'dde-link': // 14.6.4 <table:
 | ||||
| 			case 'dde-source': // 14.6.5 <office:
 | ||||
| 				break; | ||||
| 
 | ||||
| 			case 'properties': break; // 13.7 <form:properties>
 | ||||
| 			case 'property': break; // 13.8 <form:property>
 | ||||
| 
 | ||||
| 			case 'a': break; // 6.1.8 hyperlink
 | ||||
| 
 | ||||
| 			/* non-standard */ | ||||
| 			case 'table-protection': break; | ||||
| 			case 'data-pilot-grand-total': break; // <table:
 | ||||
| 			default: | ||||
| 				if(Rn[2] === 'dc:') break; // TODO: properties
 | ||||
| 				if(Rn[2] === 'draw:') break; // TODO: drawing
 | ||||
| 				if(Rn[2] === 'calcext:') break; // ignore undocumented extensions
 | ||||
| 				if(opts.WTF) throw Rn; | ||||
| 		} | ||||
| 		var out = { | ||||
| 			Sheets: Sheets, | ||||
| @ -405,10 +559,81 @@ var parse_content_xml = (function() { | ||||
| 		return out; | ||||
| 	}; | ||||
| })(); | ||||
| var write_content_xml = (function() { | ||||
| 	var null_cell_xml = '          <table:table-cell />\n'; | ||||
| 	var write_ws = function(ws, wb, i, opts) { | ||||
| 		/* Section 9 Tables */ | ||||
| 		var o = []; | ||||
| 		o.push('      <table:table table:name="' + escapexml(wb.SheetNames[i]) + '">\n'); | ||||
| 		var R=0,C=0, range = get_utils().decode_range(ws['!ref']); | ||||
| 		for(R = 0; R < range.s.r; ++R) o.push('        <table:table-row></table:table-row>\n'); | ||||
| 		for(; R <= range.e.r; ++R) { | ||||
| 			o.push('        <table:table-row>\n'); | ||||
| 			for(C=0; C < range.s.c; ++C) o.push(null_cell_xml); | ||||
| 			for(; C <= range.e.c; ++C) { | ||||
| 				var ref = get_utils().encode_cell({r:R, c:C}), cell = ws[ref]; | ||||
| 				if(cell) switch(cell.t) { | ||||
| 					case 'b': o.push('          <table:table-cell office:value-type="boolean" office:boolean-value="' + (cell.v ? 'true' : 'false') + '"><text:p>' + (cell.v ? 'TRUE' : 'FALSE') + '</text:p></table:table-cell>\n'); break; | ||||
| 					case 'n': o.push('          <table:table-cell office:value-type="float" office:value="' + cell.v + '"><text:p>' + (cell.w||cell.v) + '</text:p></table:table-cell>\n'); break; | ||||
| 					case 's': case 'str': o.push('          <table:table-cell office:value-type="string"><text:p>' + escapexml(cell.v) + '</text:p></table:table-cell>\n'); break; | ||||
| 					//case 'd': // TODO
 | ||||
| 					//case 'e':
 | ||||
| 					default: o.push(null_cell_xml); | ||||
| 				} else o.push(null_cell_xml); | ||||
| 			} | ||||
| 			o.push('        </table:table-row>\n'); | ||||
| 		} | ||||
| 		o.push('      </table:table>\n'); | ||||
| 		return o.join(""); | ||||
| 	}; | ||||
| 
 | ||||
| 	return function wcx(wb, opts) { | ||||
| 		var o = [XML_HEADER]; | ||||
| 		/* 3.1.3.2 */ | ||||
| 		o.push('<office:document-content office:version="1.2" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0">\n'); // TODO
 | ||||
| 		o.push('  <office:body>\n'); | ||||
| 		o.push('    <office:spreadsheet>\n'); | ||||
| 		for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts)); | ||||
| 		o.push('    </office:spreadsheet>\n'); | ||||
| 		o.push('  </office:body>\n'); | ||||
| 		o.push('</office:document-content>'); | ||||
| 		return o.join(""); | ||||
| 	}; | ||||
| })(); | ||||
| /* Part 3: Packages */ | ||||
| var parse_ods = function(zip, opts) { | ||||
| 	//var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'));
 | ||||
| function parse_ods(zip, opts) { | ||||
| 	opts = opts || ({}); | ||||
| 	var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts); | ||||
| 	return parse_content_xml(getzipdata(zip, 'content.xml'), opts); | ||||
| }; | ||||
| } | ||||
| function write_ods(wb, opts) { | ||||
| var zip = new jszip(); | ||||
| 	var f = ""; | ||||
| 
 | ||||
| 	var manifest = []; | ||||
| 	var rdf = []; | ||||
| 
 | ||||
| 	/* 3:3.3 and 2:2.2.4 */ | ||||
| 	f = "mimetype"; | ||||
| 	zip.file(f, "application/vnd.oasis.opendocument.spreadsheet"); | ||||
| 
 | ||||
| 	/* Part 2 Section 2.2 Documents */ | ||||
| 	f = "content.xml"; | ||||
| 	zip.file(f, write_content_xml(wb, opts)); | ||||
| 	manifest.push([f, "text/xml"]); | ||||
| 	rdf.push([f, "ContentFile"]); | ||||
| 
 | ||||
| 	/* Part 3 Section 6 Metadata Manifest File */ | ||||
| 	f = "manifest.rdf"; | ||||
| 	zip.file(f, write_rdf(rdf, opts)); | ||||
| 	manifest.push([f, "application/rdf+xml"]); | ||||
| 
 | ||||
| 	/* Part 3 Section 4 Manifest File */ | ||||
| 	f = "META-INF/manifest.xml"; | ||||
| 	zip.file(f, write_manifest(manifest, opts)); | ||||
| 
 | ||||
| 	return zip; | ||||
| } | ||||
| ODS.parse_ods = parse_ods; | ||||
| ODS.write_ods = write_ods; | ||||
| })(typeof exports !== 'undefined' ? exports : ODS); | ||||
|  | ||||
							
								
								
									
										2
									
								
								dist/ods.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										2
									
								
								dist/ods.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								dist/ods.min.map
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										1
									
								
								dist/ods.min.map
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										20
									
								
								dist/xlsx.core.min.js
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										20
									
								
								dist/xlsx.core.min.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2
									
								
								dist/xlsx.core.min.map
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										2
									
								
								dist/xlsx.core.min.map
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										18
									
								
								dist/xlsx.full.min.js
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										18
									
								
								dist/xlsx.full.min.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2
									
								
								dist/xlsx.full.min.map
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										2
									
								
								dist/xlsx.full.min.map
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										172
									
								
								dist/xlsx.js
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										172
									
								
								dist/xlsx.js
									
									
									
									
										vendored
									
									
								
							| @ -4,7 +4,7 @@ | ||||
| /*jshint funcscope:true, eqnull:true */ | ||||
| var XLSX = {}; | ||||
| (function make_xlsx(XLSX){ | ||||
| XLSX.version = '0.8.1'; | ||||
| XLSX.version = '0.8.2'; | ||||
| var current_codepage = 1200, current_cptable; | ||||
| if(typeof module !== "undefined" && typeof require !== 'undefined') { | ||||
| 	if(typeof cptable === 'undefined') cptable = require('./dist/cpexcel'); | ||||
| @ -1645,7 +1645,8 @@ function WriteShift(t, val, f) { | ||||
| 		size = 2 * val.length; | ||||
| 	} else switch(t) { | ||||
| 		case  1: size = 1; this[this.l] = val&255; break; | ||||
| 		case  3: size = 3; this[this.l+2] = val & 255; val >>>= 8; this[this.l+1] = val&255; val >>>= 8; this[this.l] = val&255; break; | ||||
| 		case  2: size = 2; this[this.l] = val&255; val >>>= 8; this[this.l+1] = val&255; break; | ||||
| 		case  3: size = 3; this[this.l] = val&255; val >>>= 8; this[this.l+1] = val&255; val >>>= 8; this[this.l+2] = val&255; break; | ||||
| 		case  4: size = 4; this.writeUInt32LE(val, this.l); break; | ||||
| 		case  8: size = 8; if(f === 'f') { this.writeDoubleLE(val, this.l); break; } | ||||
| 		/* falls through */ | ||||
| @ -1706,7 +1707,7 @@ function buf_array() { | ||||
| 	var curbuf = newblk(blksz); | ||||
| 
 | ||||
| 	var endbuf = function ba_endbuf() { | ||||
| 		curbuf.length = curbuf.l; | ||||
| 		if(curbuf.length > curbuf.l) curbuf = curbuf.slice(0, curbuf.l); | ||||
| 		if(curbuf.length > 0) bufs.push(curbuf); | ||||
| 		curbuf = null; | ||||
| 	}; | ||||
| @ -1893,6 +1894,15 @@ function parse_RkNumber(data) { | ||||
| 	var RK = fInt === 0 ? __double([0,0,0,0,b[0],b[1],b[2],b[3]],0) : __readInt32LE(b,0)>>2; | ||||
| 	return fX100 ? RK/100 : RK; | ||||
| } | ||||
| function write_RkNumber(data, o) { | ||||
| 	if(o == null) o = new_buf(4); | ||||
| 	var fX100 = 0, fInt = 0, d100 = data * 100; | ||||
| 	if(data == (data | 0) && data >= -(1<<29) && data < (1 << 29)) { fInt = 1; } | ||||
| 	else if(d100 == (d100 | 0) && d100 >= -(1<<29) && d100 < (1 << 29)) { fInt = 1; fX100 = 1; } | ||||
| 	if(fInt) o.write_shift(-4, ((fX100 ? d100 : data) << 2) + (fX100 + 2)); | ||||
| 	else throw new Error("unsupported RkNumber " + data); // TODO
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* [MS-XLSB] 2.5.153 */ | ||||
| function parse_UncheckedRfX(data) { | ||||
| @ -1915,8 +1925,9 @@ function write_UncheckedRfX(r, o) { | ||||
| 
 | ||||
| /* [MS-XLSB] 2.5.171 */ | ||||
| /* [MS-XLS] 2.5.342 */ | ||||
| /* TODO: error checking, NaN and Infinity values are not valid Xnum */ | ||||
| function parse_Xnum(data, length) { return data.read_shift(8, 'f'); } | ||||
| function write_Xnum(data, o) { return (o || new_buf(8)).write_shift(8, 'f', data); } | ||||
| function write_Xnum(data, o) { return (o || new_buf(8)).write_shift(8, data, 'f'); } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.5.198.2 */ | ||||
| var BErr = { | ||||
| @ -2730,7 +2741,7 @@ function parse_cust_props(data, opts) { | ||||
| 						p[name] = unescapexml(text); | ||||
| 						break; | ||||
| 					default: | ||||
| 						if(typeof console !== 'undefined') console.warn('Unexpected', x, type, toks); | ||||
| 						if(opts.WTF && typeof console !== 'undefined') console.warn('Unexpected', x, type, toks); | ||||
| 				} | ||||
| 			} else if(x.substr(0,2) === "</") { | ||||
| 			} else if(opts.WTF) throw new Error(x); | ||||
| @ -7286,7 +7297,7 @@ function parse_ws_xml(data, opts, rels) { | ||||
| 	var mergecells = []; | ||||
| 	if(data.indexOf("</mergeCells>")!==-1) { | ||||
| 		var merges = data.match(mergecregex); | ||||
| 		for(ridx = 0; ridx != merges.length; ++ridx) | ||||
| 		if(merges) for(ridx = 0; ridx != merges.length; ++ridx) | ||||
| 			mergecells[ridx] = safe_decode_range(merges[ridx].substr(merges[ridx].indexOf("\"")+1)); | ||||
| 	} | ||||
| 
 | ||||
| @ -7298,7 +7309,7 @@ function parse_ws_xml(data, opts, rels) { | ||||
| 		parse_ws_xml_cols(columns, cols); | ||||
| 	} | ||||
| 
 | ||||
| 	var refguess = {s: {r:1000000, c:1000000}, e: {r:0, c:0} }; | ||||
| 	var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} }; | ||||
| 
 | ||||
| 	/* 18.3.1.80 sheetData CT_SheetData ? */ | ||||
| 	var mtch=data.match(sheetdataregex); | ||||
| @ -7573,6 +7584,45 @@ function parse_BrtRowHdr(data, length) { | ||||
| 	data.l += length-4; | ||||
| 	return z; | ||||
| } | ||||
| function write_BrtRowHdr(R, range, ws) { | ||||
| 	var o = new_buf(17+8*16); | ||||
| 	o.write_shift(4, R); | ||||
| 
 | ||||
| 	/* TODO: flags styles */ | ||||
| 	o.write_shift(4, 0); | ||||
| 	o.write_shift(2, 0x0140); | ||||
| 	o.write_shift(2, 0); | ||||
| 	o.write_shift(1, 0); | ||||
| 
 | ||||
| 	/* [MS-XLSB] 2.5.8 BrtColSpan explains the mechanism */ | ||||
| 	var ncolspan = 0, lcs = o.l; | ||||
| 	o.l += 4; | ||||
| 
 | ||||
| 	var caddr = {r:R, c:0}; | ||||
| 	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; | ||||
| 			if(ws[encode_cell(caddr)]) { if(first < 0) first = j; last = j; } | ||||
| 		} | ||||
| 		if(first < 0) continue; | ||||
| 		++ncolspan; | ||||
| 		o.write_shift(4, first); | ||||
| 		o.write_shift(4, last); | ||||
| 	} | ||||
| 
 | ||||
| 	var l = o.l; | ||||
| 	o.l = lcs; | ||||
| 	o.write_shift(4, ncolspan); | ||||
| 	o.l = l; | ||||
| 
 | ||||
| 	return o.length > o.l ? o.slice(0, o.l) : o; | ||||
| } | ||||
| function write_row_header(ba, ws, range, R) { | ||||
| 	var o = write_BrtRowHdr(R, range, ws); | ||||
| 	if(o.length > 17) write_record(ba, 'BrtRowHdr', o); | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.812 BrtWsDim */ | ||||
| var parse_BrtWsDim = parse_UncheckedRfX; | ||||
| @ -7592,9 +7642,9 @@ function parse_BrtCellBlank(data, length) { | ||||
| 	var cell = parse_XLSBCell(data); | ||||
| 	return [cell]; | ||||
| } | ||||
| function write_BrtCellBlank(cell, val, o) { | ||||
| function write_BrtCellBlank(cell, ncell, o) { | ||||
| 	if(o == null) o = new_buf(8); | ||||
| 	return write_XLSBCell(val, o); | ||||
| 	return write_XLSBCell(ncell, o); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| @ -7604,12 +7654,18 @@ function parse_BrtCellBool(data, length) { | ||||
| 	var fBool = data.read_shift(1); | ||||
| 	return [cell, fBool, 'b']; | ||||
| } | ||||
| function write_BrtCellBool(cell, ncell, o) { | ||||
| 	if(o == null) o = new_buf(9); | ||||
| 	write_XLSBCell(ncell, o); | ||||
| 	o.write_shift(1, cell.v ? 1 : 0); | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.305 BrtCellError */ | ||||
| function parse_BrtCellError(data, length) { | ||||
| 	var cell = parse_XLSBCell(data); | ||||
| 	var fBool = data.read_shift(1); | ||||
| 	return [cell, fBool, 'e']; | ||||
| 	var bError = data.read_shift(1); | ||||
| 	return [cell, bError, 'e']; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.308 BrtCellIsst */ | ||||
| @ -7618,6 +7674,12 @@ function parse_BrtCellIsst(data, length) { | ||||
| 	var isst = data.read_shift(4); | ||||
| 	return [cell, isst, 's']; | ||||
| } | ||||
| function write_BrtCellIsst(cell, ncell, o) { | ||||
| 	if(o == null) o = new_buf(12); | ||||
| 	write_XLSBCell(ncell, o); | ||||
| 	o.write_shift(4, ncell.v); | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.310 BrtCellReal */ | ||||
| function parse_BrtCellReal(data, length) { | ||||
| @ -7625,6 +7687,12 @@ function parse_BrtCellReal(data, length) { | ||||
| 	var value = parse_Xnum(data); | ||||
| 	return [cell, value, 'n']; | ||||
| } | ||||
| function write_BrtCellReal(cell, ncell, o) { | ||||
| 	if(o == null) o = new_buf(16); | ||||
| 	write_XLSBCell(ncell, o); | ||||
| 	write_Xnum(cell.v, o); | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.311 BrtCellRk */ | ||||
| function parse_BrtCellRk(data, length) { | ||||
| @ -7632,6 +7700,13 @@ function parse_BrtCellRk(data, length) { | ||||
| 	var value = parse_RkNumber(data); | ||||
| 	return [cell, value, 'n']; | ||||
| } | ||||
| function write_BrtCellRk(cell, ncell, o) { | ||||
| 	if(o == null) o = new_buf(12); | ||||
| 	write_XLSBCell(ncell, o); | ||||
| 	write_RkNumber(cell.v, o); | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.314 BrtCellSt */ | ||||
| function parse_BrtCellSt(data, length) { | ||||
| @ -7639,6 +7714,12 @@ function parse_BrtCellSt(data, length) { | ||||
| 	var value = parse_XLWideString(data); | ||||
| 	return [cell, value, 'str']; | ||||
| } | ||||
| function write_BrtCellSt(cell, ncell, o) { | ||||
| 	if(o == null) o = new_buf(12 + 4 * cell.v.length); | ||||
| 	write_XLSBCell(ncell, o); | ||||
| 	write_XLWideString(cell.v, o); | ||||
| 	return o.length > o.l ? o.slice(0, o.l) : o; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.647 BrtFmlaBool */ | ||||
| function parse_BrtFmlaBool(data, length, opts) { | ||||
| @ -7714,12 +7795,13 @@ function parse_ws_bin(data, opts, rels) { | ||||
| 	var s = {}; | ||||
| 
 | ||||
| 	var ref; | ||||
| 	var refguess = {s: {r:1000000, c:1000000}, e: {r:0, c:0} }; | ||||
| 	var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} }; | ||||
| 
 | ||||
| 	var pass = false, end = false; | ||||
| 	var row, p, cf, R, C, addr, sstr, rr; | ||||
| 	var mergecells = []; | ||||
| 	recordhopper(data, function ws_parse(val, R) { | ||||
| 		//console.log(R);
 | ||||
| 		if(end) return; | ||||
| 		switch(R.n) { | ||||
| 			case 'BrtWsDim': ref = val; break; | ||||
| @ -7896,7 +7978,7 @@ function parse_ws_bin(data, opts, rels) { | ||||
| 			default: if(!pass || opts.WTF) throw new Error("Unexpected record " + R.n); | ||||
| 		} | ||||
| 	}, opts); | ||||
| 	if(!s["!ref"] && (refguess.s.r < 1000000 || ref.e.r > 0 || ref.e.c > 0 || ref.s.r > 0 || ref.s.c > 0)) s["!ref"] = encode_range(ref); | ||||
| 	if(!s["!ref"] && (refguess.s.r < 2000000 || ref.e.r > 0 || ref.e.c > 0 || ref.s.r > 0 || ref.s.c > 0)) s["!ref"] = encode_range(ref); | ||||
| 	if(opts.sheetRows && s["!ref"]) { | ||||
| 		var tmpref = safe_decode_range(s["!ref"]); | ||||
| 		if(opts.sheetRows < +tmpref.e.r) { | ||||
| @ -7929,12 +8011,23 @@ function write_ws_bin_cell(ba, cell, R, C, opts) { | ||||
| 		case 's': case 'str': | ||||
| 			if(opts.bookSST) { | ||||
| 				vv = get_sst_id(opts.Strings, cell.v); | ||||
| 				o.t = "s"; break; | ||||
| 				o.t = "s"; o.v = vv; | ||||
| 				write_record(ba, "BrtCellIsst", write_BrtCellIsst(cell, o)); | ||||
| 			} else { | ||||
| 				o.t = "str"; | ||||
| 				write_record(ba, "BrtCellSt", write_BrtCellSt(cell, o)); | ||||
| 			} | ||||
| 			o.t = "str"; break; | ||||
| 		case 'n': break; | ||||
| 		case 'b': o.t = "b"; break; | ||||
| 		case 'e': o.t = "e"; break; | ||||
| 			return; | ||||
| 		case 'n': | ||||
| 			/* TODO: determine threshold for Real vs RK */ | ||||
| 			if(cell.v == (cell.v | 0) && cell.v > -1000 && cell.v < 1000) write_record(ba, "BrtCellRk", write_BrtCellRk(cell, o)); | ||||
| 			else write_record(ba, "BrtCellReal", write_BrtCellReal(cell, o)); | ||||
| 			return; | ||||
| 		case 'b': | ||||
| 			o.t = "b"; | ||||
| 			write_record(ba, "BrtCellBool", write_BrtCellBool(cell, o)); | ||||
| 			return; | ||||
| 		case 'e': /* TODO: error */ o.t = "e"; break; | ||||
| 	} | ||||
| 	write_record(ba, "BrtCellBlank", write_BrtCellBlank(cell, o)); | ||||
| } | ||||
| @ -7946,6 +8039,7 @@ function write_CELLTABLE(ba, ws, idx, opts, wb) { | ||||
| 		rr = encode_row(R); | ||||
| 		/* [ACCELLTABLE] */ | ||||
| 		/* BrtRowHdr */ | ||||
| 		write_row_header(ba, ws, range, R); | ||||
| 		for(var C = range.s.c; C <= range.e.c; ++C) { | ||||
| 			/* *16384CELL */ | ||||
| 			if(R === range.s.r) cols[C] = encode_col(C); | ||||
| @ -8258,7 +8352,7 @@ function write_BrtBundleSh(data, o) { | ||||
| 	o.write_shift(4, data.iTabID); | ||||
| 	write_RelID(data.strRelID, o); | ||||
| 	write_XLWideString(data.name.substr(0,31), o); | ||||
| 	return o; | ||||
| 	return o.length > o.l ? o.slice(0, o.l) : o; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.807 BrtWbProp */ | ||||
| @ -8366,7 +8460,7 @@ function write_BrtFileVersion(data, o) { | ||||
| 	write_XLWideString(XLSX.version, o); | ||||
| 	write_XLWideString("7262", o); | ||||
| 	o.length = o.l; | ||||
| 	return o; | ||||
| 	return o.length > o.l ? o.slice(0, o.l) : o; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.1.7.60 Workbook */ | ||||
| @ -8389,6 +8483,7 @@ function write_BrtCalcProp(data, o) { | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.640 BrtFileRecover */ | ||||
| function write_BrtFileRecover(data, o) { | ||||
| 	if(!o) o = new_buf(1); | ||||
| 	o.write_shift(1,0); | ||||
| @ -8401,22 +8496,22 @@ function write_wb_bin(wb, opts) { | ||||
| 	write_record(ba, "BrtBeginBook"); | ||||
| 	write_record(ba, "BrtFileVersion", write_BrtFileVersion()); | ||||
| 	/* [[BrtFileSharingIso] BrtFileSharing] */ | ||||
| 	write_record(ba, "BrtWbProp", write_BrtWbProp()); | ||||
| 	if(0) write_record(ba, "BrtWbProp", write_BrtWbProp()); | ||||
| 	/* [ACABSPATH] */ | ||||
| 	/* [[BrtBookProtectionIso] BrtBookProtection] */ | ||||
| 	write_BOOKVIEWS(ba, wb, opts); | ||||
| 	if(0) write_BOOKVIEWS(ba, wb, opts); | ||||
| 	write_BUNDLESHS(ba, wb, opts); | ||||
| 	/* [FNGROUP] */ | ||||
| 	/* [EXTERNALS] */ | ||||
| 	/* *BrtName */ | ||||
| 	write_record(ba, "BrtCalcProp", write_BrtCalcProp()); | ||||
| 	if(0) write_record(ba, "BrtCalcProp", write_BrtCalcProp()); | ||||
| 	/* [BrtOleSize] */ | ||||
| 	/* *(BrtUserBookView *FRT) */ | ||||
| 	/* [PIVOTCACHEIDS] */ | ||||
| 	/* [BrtWbFactoid] */ | ||||
| 	/* [SMARTTAGTYPES] */ | ||||
| 	/* [BrtWebOpt] */ | ||||
| 	write_record(ba, "BrtFileRecover", write_BrtFileRecover()); | ||||
| 	if(0) write_record(ba, "BrtFileRecover", write_BrtFileRecover()); | ||||
| 	/* [WEBPUBITEMS] */ | ||||
| 	/* [CRERRS] */ | ||||
| 	/* FRTWORKBOOK */ | ||||
| @ -8625,7 +8720,7 @@ function parse_xlml_xml(d, opts) { | ||||
| 	var sheets = {}, sheetnames = [], cursheet = {}, sheetname = ""; | ||||
| 	var table = {}, cell = {}, row = {}, dtag, didx; | ||||
| 	var c = 0, r = 0; | ||||
| 	var refguess = {s: {r:1000000, c:1000000}, e: {r:0, c:0} }; | ||||
| 	var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} }; | ||||
| 	var styles = {}, stag = {}; | ||||
| 	var ss = "", fidx = 0; | ||||
| 	var mergecells = []; | ||||
| @ -8685,7 +8780,7 @@ function parse_xlml_xml(d, opts) { | ||||
| 				if(mergecells.length) cursheet["!merges"] = mergecells; | ||||
| 				sheets[sheetname] = cursheet; | ||||
| 			} else { | ||||
| 				refguess = {s: {r:1000000, c:1000000}, e: {r:0, c:0} }; | ||||
| 				refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} }; | ||||
| 				r = c = 0; | ||||
| 				state.push([Rn[3], false]); | ||||
| 				tmp = xlml_parsexmltag(Rn[0]); | ||||
| @ -11080,12 +11175,17 @@ var XLSRecordEnum = { | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| /* Helper function to call out to ODS parser */ | ||||
| /* Helper functions to call out to ODS */ | ||||
| function parse_ods(zip, opts) { | ||||
| 	if(typeof module !== "undefined" && typeof require !== 'undefined' && typeof ODS === 'undefined') ODS = require('./od' + 's'); | ||||
| 	if(typeof ODS === 'undefined' || !ODS.parse_ods) throw new Error("Unsupported ODS"); | ||||
| 	return ODS.parse_ods(zip, opts); | ||||
| } | ||||
| function write_ods(wb, opts) { | ||||
| 	if(typeof module !== "undefined" && typeof require !== 'undefined' && typeof ODS === 'undefined') ODS = require('./od' + 's'); | ||||
| 	if(typeof ODS === 'undefined' || !ODS.write_ods) throw new Error("Unsupported ODS"); | ||||
| 	return ODS.write_ods(wb, opts); | ||||
| } | ||||
| function fix_opts_func(defaults) { | ||||
| 	return function fix_opts(opts) { | ||||
| 		for(var i = 0; i != defaults.length; ++i) { | ||||
| @ -11124,6 +11224,8 @@ var fix_write_opts = fix_opts_func([ | ||||
| 
 | ||||
| 	['bookType', 'xlsx'], /* Type of workbook (xlsx/m/b) */ | ||||
| 
 | ||||
| 	['compression', false], /* Use file compression */ | ||||
| 
 | ||||
| 	['WTF', false] /* WTF mode (throws errors) */ | ||||
| ]); | ||||
| function safe_parse_wbrels(wbrels, sheets) { | ||||
| @ -11278,6 +11380,7 @@ function add_rels(rels, rId, f, type, relobj) { | ||||
| } | ||||
| 
 | ||||
| function write_zip(wb, opts) { | ||||
| 	if(opts.bookType == "ods") return write_ods(wb, opts); | ||||
| 	if(wb && !wb.SSF) { | ||||
| 		wb.SSF = SSF.get_table(); | ||||
| 	} | ||||
| @ -11405,13 +11508,17 @@ function readFileSync(data, opts) { | ||||
| function write_zip_type(wb, opts) { | ||||
| 	var o = opts||{}; | ||||
| 	var z = write_zip(wb, o); | ||||
| 	var oopts = {}; | ||||
| 	if(opts.compression) oopts.compression = 'DEFLATE'; | ||||
| 	switch(o.type) { | ||||
| 		case "base64": return z.generate({type:"base64"}); | ||||
| 		case "binary": return z.generate({type:"string"}); | ||||
| 		case "buffer": return z.generate({type:"nodebuffer"}); | ||||
| 		case "file": return _fs.writeFileSync(o.file, z.generate({type:"nodebuffer"})); | ||||
| 		case "base64": oopts.type = "base64"; break; | ||||
| 		case "binary": oopts.type = "string"; break; | ||||
| 		case "buffer": | ||||
| 		case "file": oopts.type = "nodebuffer"; break; | ||||
| 		default: throw new Error("Unrecognized type " + o.type); | ||||
| 	} | ||||
| 	if(o.type === "file") return _fs.writeFileSync(o.file, z.generate(oopts)); | ||||
| 	return z.generate(oopts); | ||||
| } | ||||
| 
 | ||||
| function writeSync(wb, opts) { | ||||
| @ -11425,13 +11532,14 @@ function writeSync(wb, opts) { | ||||
| function writeFileSync(wb, filename, opts) { | ||||
| 	var o = opts||{}; o.type = 'file'; | ||||
| 	o.file = filename; | ||||
| 	switch(o.file.substr(-5).toLowerCase()) { | ||||
| 	if(!o.bookType) switch(o.file.substr(-5).toLowerCase()) { | ||||
| 		case '.xlsx': o.bookType = 'xlsx'; break; | ||||
| 		case '.xlsm': o.bookType = 'xlsm'; break; | ||||
| 		case '.xlsb': o.bookType = 'xlsb'; break; | ||||
| 	default: switch(o.file.substr(-4).toLowerCase()) { | ||||
| 		case '.xls': o.bookType = 'xls'; break; | ||||
| 		case '.xml': o.bookType = 'xml'; break; | ||||
| 		case '.ods': o.bookType = 'ods'; break; | ||||
| 	}} | ||||
| 	return writeSync(wb, o); | ||||
| } | ||||
|  | ||||
							
								
								
									
										17
									
								
								dist/xlsx.min.js
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										17
									
								
								dist/xlsx.min.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2
									
								
								dist/xlsx.min.map
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										2
									
								
								dist/xlsx.min.map
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @ -21,7 +21,7 @@ | ||||
| </style> | ||||
| </head> | ||||
| <body> | ||||
| <b>JS-XLSX (XLSX/XLSB/XLSM/XLS/XML) Live Demo</b><br /> | ||||
| <b>JS-XLSX (XLSX/XLSB/XLSM/XLS/XML/ODS) Live Demo</b><br /> | ||||
| Output Format: | ||||
| <select name="format"> | ||||
| <option value="csv" selected> CSV</option> | ||||
| @ -48,7 +48,7 @@ Use readAsBinaryString: (when available) <input type="checkbox" name="userabs" c | ||||
| <script src="jszip.js"></script> | ||||
| <script src="xlsx.js"></script> | ||||
| <!-- uncomment the next line here and in xlsxworker.js for ODS support --> | ||||
| <script src="dist/ods.js"></script> | ||||
| <script src="ods.js"></script> | ||||
| <script> | ||||
| var X = XLSX; | ||||
| var XW = { | ||||
|  | ||||
							
								
								
									
										12
									
								
								misc/flow.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										12
									
								
								misc/flow.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| /*:: | ||||
| type ZIPFile = any; | ||||
| 
 | ||||
| type ParseOpts = any; | ||||
| 
 | ||||
| type Workbook = { | ||||
| 	SheetNames: Array<string>; | ||||
| 	Sheets: any; | ||||
| }; | ||||
| 
 | ||||
| type XLSXModule = any; | ||||
| */ | ||||
							
								
								
									
										8
									
								
								misc/flowdeps.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										8
									
								
								misc/flowdeps.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| /*:: | ||||
| declare module 'exit-on-epipe' {}; | ||||
| 
 | ||||
| declare module 'xlsx' { declare var exports:XLSXModule; }; | ||||
| declare module '../' { declare var exports:XLSXModule; }; | ||||
| 
 | ||||
| declare module 'commander' { declare var exports:any; }; | ||||
| */ | ||||
							
								
								
									
										642
									
								
								ods.flow.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										642
									
								
								ods.flow.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,642 @@ | ||||
| /* ods.js (C) 2014-present  SheetJS -- http://sheetjs.com */ | ||||
| /* vim: set ts=2: */ | ||||
| /*jshint -W041 */ | ||||
| var ODS = {}; | ||||
| (function make_ods(ODS) { | ||||
| /* Open Document Format for Office Applications (OpenDocument) Version 1.2 */ | ||||
| /*:: declare var XLSX: any; */ | ||||
| var get_utils = function() { | ||||
| 	if(typeof XLSX !== 'undefined') return XLSX.utils; | ||||
| 	if(typeof module !== "undefined" && typeof require !== 'undefined') try { | ||||
| 		return require('../' + 'xlsx').utils; | ||||
| 	} catch(e) { | ||||
| 		try { return require('./' + 'xlsx').utils; } | ||||
| 		catch(ee) { return require('xl' + 'sx').utils; } | ||||
| 	} | ||||
| 	throw new Error("Cannot find XLSX utils"); | ||||
| }; | ||||
| var has_buf = (typeof Buffer !== 'undefined'); | ||||
| 
 | ||||
| function cc2str(arr) { | ||||
| 	var o = ""; | ||||
| 	for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]); | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| function dup(o/*:object*/)/*:object*/ { | ||||
| 	if(typeof JSON != 'undefined') return JSON.parse(JSON.stringify(o)); | ||||
| 	if(typeof o != 'object' || !o) return o; | ||||
| 	var out = {}; | ||||
| 	for(var k in o) if(o.hasOwnProperty(k)) out[k] = dup(o[k]); | ||||
| 	return out; | ||||
| } | ||||
| function getdata(data) { | ||||
| 	if(!data) return null; | ||||
| 	if(data.data) return data.data; | ||||
| 	if(data.asNodeBuffer && has_buf) return data.asNodeBuffer().toString('binary'); | ||||
| 	if(data.asBinary) return data.asBinary(); | ||||
| 	if(data._data && data._data.getContent) return cc2str(Array.prototype.slice.call(data._data.getContent(),0)); | ||||
| 	return null; | ||||
| } | ||||
| 
 | ||||
| function safegetzipfile(zip, file) { | ||||
| 	var f = file; if(zip.files[f]) return zip.files[f]; | ||||
| 	f = file.toLowerCase(); if(zip.files[f]) return zip.files[f]; | ||||
| 	f = f.replace(/\//g,'\\'); if(zip.files[f]) return zip.files[f]; | ||||
| 	return null; | ||||
| } | ||||
| 
 | ||||
| function getzipfile(zip, file) { | ||||
| 	var o = safegetzipfile(zip, file); | ||||
| 	if(o == null) throw new Error("Cannot find file " + file + " in zip"); | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| function getzipdata(zip, file, safe/*:?boolean*/) { | ||||
| 	if(!safe) return getdata(getzipfile(zip, file)); | ||||
| 	if(!file) return null; | ||||
| 	try { return getzipdata(zip, file); } catch(e) { return null; } | ||||
| } | ||||
| 
 | ||||
| var _fs, jszip; | ||||
| /*:: declare var JSZip:any; */ | ||||
| if(typeof JSZip !== 'undefined') jszip = JSZip; | ||||
| if (typeof exports !== 'undefined') { | ||||
| 	if (typeof module !== 'undefined' && module.exports) { | ||||
| 		if(has_buf && typeof jszip === 'undefined') jszip = require('js'+'zip'); | ||||
| 		if(typeof jszip === 'undefined') jszip = require('./js'+'zip').JSZip; | ||||
| 		_fs = require('f'+'s'); | ||||
| 	} | ||||
| } | ||||
| var attregexg=/\b[\w:-]+=["'][^"]*['"]/g; | ||||
| var tagregex=/<[^>]*>/g; | ||||
| var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/; | ||||
| function parsexmltag(tag, skip_root) { | ||||
| 	var z/*:any*/ = []; | ||||
| 	var eq = 0, c = 0; | ||||
| 	for(; eq !== tag.length; ++eq) if((c = tag.charCodeAt(eq)) === 32 || c === 10 || c === 13) break; | ||||
| 	if(!skip_root) z[0] = tag.substr(0, eq); | ||||
| 	if(eq === tag.length) return z; | ||||
| 	var m = tag.match(attregexg), j=0, v="", i=0, q="", cc=""; | ||||
| 	if(m) for(i = 0; i != m.length; ++i) { | ||||
| 		cc = m[i]; | ||||
| 		for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break; | ||||
| 		q = cc.substr(0,c); v = cc.substring(c+2, cc.length-1); | ||||
| 		for(j=0;j!=q.length;++j) if(q.charCodeAt(j) === 58) break; | ||||
| 		if(j===q.length) z[q] = v; | ||||
| 		else z[(j===5 && q.substr(0,5)==="xmlns"?"xmlns":"")+q.substr(j+1)] = v; | ||||
| 	} | ||||
| 	return z; | ||||
| } | ||||
| function strip_ns(x) { return x.replace(nsregex2, "<$1"); } | ||||
| 
 | ||||
| var encodings = { | ||||
| 	'"': '"', | ||||
| 	''': "'", | ||||
| 	'>': '>', | ||||
| 	'<': '<', | ||||
| 	'&': '&' | ||||
| }; | ||||
| var rencoding = { | ||||
| 	'"': '"', | ||||
| 	"'": ''', | ||||
| 	'>': '>', | ||||
| 	'<': '<', | ||||
| 	'&': '&' | ||||
| }; | ||||
| var rencstr = "&<>'\"".split(""); | ||||
| 
 | ||||
| // TODO: CP remap (need to read file version to determine OS)
 | ||||
| var encregex = /&[a-z]*;/g, coderegex = /_x([\da-fA-F]+)_/g; | ||||
| function unescapexml(text){ | ||||
| 	var s = text + ''; | ||||
| 	return s.replace(encregex, function($$) { return encodings[$$]; }).replace(coderegex,function(m,c) {return String.fromCharCode(parseInt(c,16));}); | ||||
| } | ||||
| var decregex=/[&<>'"]/g, charegex = /[\u0000-\u0008\u000b-\u001f]/g; | ||||
| function escapexml(text){ | ||||
| 	var s = text + ''; | ||||
| 	return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).substr(-4) + "_";}); | ||||
| } | ||||
| 
 | ||||
| function parsexmlbool(value) { | ||||
| 	switch(value) { | ||||
| 		case '1': case 'true': case 'TRUE': return true; | ||||
| 		/* case '0': case 'false': case 'FALSE':*/ | ||||
| 		default: return false; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| function datenum(v) { | ||||
| 	var epoch = Date.parse(v); | ||||
| 	return (epoch + 2209161600000) / (24 * 60 * 60 * 1000); | ||||
| } | ||||
| 
 | ||||
| /* ISO 8601 Duration */ | ||||
| function parse_isodur(s) { | ||||
| 	var sec = 0, mt = 0, time = false; | ||||
| 	var m = s.match(/P([0-9\.]+Y)?([0-9\.]+M)?([0-9\.]+D)?T([0-9\.]+H)?([0-9\.]+M)?([0-9\.]+S)?/); | ||||
| 	if(!m) throw new Error("|" + s + "| is not an ISO8601 Duration"); | ||||
| 	for(var i = 1; i != m.length; ++i) { | ||||
| 		if(!m[i]) continue; | ||||
| 		mt = 1; | ||||
| 		if(i > 3) time = true; | ||||
| 		switch(m[i].substr(m[i].length-1)) { | ||||
| 			case 'Y': | ||||
| 				throw new Error("Unsupported ISO Duration Field: " + m[i].substr(m[i].length-1)); | ||||
| 			case 'D': mt *= 24; | ||||
| 				/* falls through */ | ||||
| 			case 'H': mt *= 60; | ||||
| 				/* falls through */ | ||||
| 			case 'M': | ||||
| 				if(!time) throw new Error("Unsupported ISO Duration Field: M"); | ||||
| 				else mt *= 60; | ||||
| 				/* falls through */ | ||||
| 			case 'S': break; | ||||
| 		} | ||||
| 		sec += mt * parseInt(m[i], 10); | ||||
| 	} | ||||
| 	return sec; | ||||
| } | ||||
| 
 | ||||
| var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n'; | ||||
| /* copied from js-xls (C) SheetJS Apache2 license */ | ||||
| function xlml_normalize(d) { | ||||
| 	if(has_buf &&/*::typeof Buffer !== "undefined" && d != null &&*/ Buffer.isBuffer(d)) return d.toString('utf8'); | ||||
| 	if(typeof d === 'string') return d; | ||||
| 	throw "badf"; | ||||
| } | ||||
| 
 | ||||
| var xlmlregex = /<(\/?)([a-z0-9]*:|)([\w-]+)[^>]*>/mg; | ||||
| /* Part 3 Section 4 Manifest File */ | ||||
| var CT_ODS = "application/vnd.oasis.opendocument.spreadsheet"; | ||||
| function parse_manifest(d, opts) { | ||||
| 	var str = xlml_normalize(d); | ||||
| 	var Rn; | ||||
| 	var FEtag; | ||||
| 	while((Rn = xlmlregex.exec(str))) switch(Rn[3]) { | ||||
| 		case 'manifest': break; // 4.2 <manifest:manifest>
 | ||||
| 		case 'file-entry': // 4.3 <manifest:file-entry>
 | ||||
| 			FEtag = parsexmltag(Rn[0], false); | ||||
| 			if(FEtag.path == '/' && FEtag.type !== CT_ODS) throw new Error("This OpenDocument is not a spreadsheet"); | ||||
| 			break; | ||||
| 		case 'encryption-data': // 4.4 <manifest:encryption-data>
 | ||||
| 		case 'algorithm': // 4.5 <manifest:algorithm>
 | ||||
| 		case 'start-key-generation': // 4.6 <manifest:start-key-generation>
 | ||||
| 		case 'key-derivation': // 4.7 <manifest:key-derivation>
 | ||||
| 			throw new Error("Unsupported ODS Encryption"); | ||||
| 		default: if(opts && opts.WTF) throw Rn; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| function write_manifest(manifest/*:Array<Array<string> >*/, opts)/*: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(""); | ||||
| } | ||||
| /* 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/*: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, opts) { | ||||
| 	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 parse_text_p = function(text, tag) { | ||||
| 	return unescapexml(utf8read(text.replace(/<text:s\/>/g," ").replace(/<[^>]*>/g,""))); | ||||
| }; | ||||
| 
 | ||||
| var utf8read = function utf8reada(orig) { | ||||
| 	var out = "", i = 0, c = 0, d = 0, e = 0, f = 0, w = 0; | ||||
| 	while (i < orig.length) { | ||||
| 		c = orig.charCodeAt(i++); | ||||
| 		if (c < 128) { out += String.fromCharCode(c); continue; } | ||||
| 		d = orig.charCodeAt(i++); | ||||
| 		if (c>191 && c<224) { out += String.fromCharCode(((c & 31) << 6) | (d & 63)); continue; } | ||||
| 		e = orig.charCodeAt(i++); | ||||
| 		if (c < 240) { out += String.fromCharCode(((c & 15) << 12) | ((d & 63) << 6) | (e & 63)); continue; } | ||||
| 		f = orig.charCodeAt(i++); | ||||
| 		w = (((c & 7) << 18) | ((d & 63) << 12) | ((e & 63) << 6) | (f & 63))-65536; | ||||
| 		out += String.fromCharCode(0xD800 + ((w>>>10)&1023)); | ||||
| 		out += String.fromCharCode(0xDC00 + (w&1023)); | ||||
| 	} | ||||
| 	return out; | ||||
| }; | ||||
| var parse_content_xml = (function() { | ||||
| 
 | ||||
| 	var number_formats = { | ||||
| 		/* ods name: [short ssf fmt, long ssf fmt] */ | ||||
| 		day: ["d", "dd"], | ||||
| 		month: ["m", "mm"], | ||||
| 		year: ["y", "yy"], | ||||
| 		hours: ["h", "hh"], | ||||
| 		minutes: ["m", "mm"], | ||||
| 		seconds: ["s", "ss"], | ||||
| 		"am-pm": ["A/P", "AM/PM"], | ||||
| 		"day-of-week": ["ddd", "dddd"] | ||||
| 	}; | ||||
| 
 | ||||
| 	return function pcx(d, opts) { | ||||
| 		var str = xlml_normalize(d); | ||||
| 		var state/*:Array<any>*/ = [], tmp; | ||||
| 		var tag/*:: = {}*/; | ||||
| 		var NFtag = {name:""}, NF = "", pidx = 0; | ||||
| 		var sheetag/*:: = {name:""}*/; | ||||
| 		var Sheets = {}, SheetNames/*:Array<string>*/ = [], ws = {}; | ||||
| 		var Rn, q/*:: = {t:"", v:null, z:null, w:""}*/; | ||||
| 		var ctag = {value:""}; | ||||
| 		var textp = "", textpidx = 0, textptag/*:: = {}*/; | ||||
| 		var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}}; | ||||
| 		var number_format_map = {}; | ||||
| 		var merges = [], mrange = {}, mR = 0, mC = 0; | ||||
| 		var rept = 1; | ||||
| 		xlmlregex.lastIndex = 0; | ||||
| 		while((Rn = xlmlregex.exec(str))) switch(Rn[3]) { | ||||
| 
 | ||||
| 			case 'table': // 9.1.2 <table:table>
 | ||||
| 				if(Rn[1]==='/') { | ||||
| 					if(range.e.c >= range.s.c && range.e.r >= range.s.r) ws['!ref'] = get_utils().encode_range(range); | ||||
| 					if(merges.length) ws['!merges'] = merges; | ||||
| 					sheetag.name = utf8read(sheetag.name); | ||||
| 					SheetNames.push(sheetag.name); | ||||
| 					Sheets[sheetag.name] = ws; | ||||
| 				} | ||||
| 				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 = {}; merges = []; | ||||
| 				} | ||||
| 				break; | ||||
| 
 | ||||
| 			case 'table-row': // 9.1.3 <table:table-row>
 | ||||
| 				if(Rn[1] === '/') break; | ||||
| 				++R; C = -1; break; | ||||
| 			case 'covered-table-cell': // 9.1.5 table:covered-table-cell
 | ||||
| 				++C; break; /* stub */ | ||||
| 			case 'table-cell': | ||||
| 				if(Rn[0].charAt(Rn[0].length-2) === '/') { | ||||
| 					ctag = parsexmltag(Rn[0], false); | ||||
| 					if(ctag['number-columns-repeated']) C+= parseInt(ctag['number-columns-repeated'], 10); | ||||
| 					else ++C; | ||||
| 				} | ||||
| 				else if(Rn[1]!=='/') { | ||||
| 					++C; | ||||
| 					rept = 1; | ||||
| 					if(C > range.e.c) range.e.c = C; | ||||
| 					if(R > range.e.r) range.e.r = R; | ||||
| 					if(C < range.s.c) range.s.c = C; | ||||
| 					if(R < range.s.r) range.s.r = R; | ||||
| 					ctag = parsexmltag(Rn[0], false); | ||||
| 					q = {t:ctag['value-type'], v:null/*:: , z:null, w:""*/}; | ||||
| 					if(ctag['number-columns-spanned'] || ctag['number-rows-spanned']) { | ||||
| 						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']) rept = parseInt(ctag['number-columns-repeated'], 10); | ||||
| 
 | ||||
| 					/* 19.385 office:value-type */ | ||||
| 					switch(q.t) { | ||||
| 						case 'boolean': q.t = 'b'; q.v = parsexmlbool(ctag['boolean-value']); break; | ||||
| 						case 'float': q.t = 'n'; q.v = parseFloat(ctag.value); break; | ||||
| 						case '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 = 'n'; q.v = datenum(ctag['date-value']); q.z = 'm/d/yy'; break; | ||||
| 						case 'time': q.t = 'n'; q.v = parse_isodur(ctag['time-value'])/86400; break; | ||||
| 						default: | ||||
| 							if(q.t === 'string' || !q.t) { | ||||
| 								q.t = 's'; | ||||
| 								if(ctag['string-value'] != null) textp = ctag['string-value']; | ||||
| 							} else throw new Error('Unsupported value type ' + q.t); | ||||
| 					} | ||||
| 				} else { | ||||
| 					if(q.t === 's') q.v = textp || ''; | ||||
| 					if(textp) q.w = textp; | ||||
| 					if(!(opts.sheetRows && opts.sheetRows < R)) { | ||||
| 						ws[get_utils().encode_cell({r:R,c:C})] = q; | ||||
| 						while(--rept > 0) ws[get_utils().encode_cell({r:R,c:++C})] = dup(q); | ||||
| 						if(range.e.c <= C) range.e.c = C; | ||||
| 					} | ||||
| 					q = {/*:: t:"", v:null, z:null, w:""*/}; | ||||
| 					textp = ""; | ||||
| 				} | ||||
| 				break; // 9.1.4 <table:table-cell>
 | ||||
| 
 | ||||
| 			/* pure state */ | ||||
| 			case 'document-content': // 3.1.3.2 <office:document-content>
 | ||||
| 			case 'spreadsheet': // 3.7 <office:spreadsheet>
 | ||||
| 			case 'scripts': // 3.12 <office:scripts>
 | ||||
| 			case 'font-face-decls': // 3.14 <office:font-face-decls>
 | ||||
| 				if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;} | ||||
| 				else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], true]); | ||||
| 				break; | ||||
| 
 | ||||
| 			/* ignore state */ | ||||
| 			case 'shapes': // 9.2.8 <table:shapes>
 | ||||
| 			case 'frame': // 10.4.2 <draw:frame>
 | ||||
| 			case 'text-box': // 10.4.3 <draw:text-box>
 | ||||
| 			case 'image': // 10.4.4 <draw:image>
 | ||||
| 			case 'data-pilot-tables': // 9.6.2 <table:data-pilot-tables>
 | ||||
| 			case 'list-style': // 16.30 <text:list-style>
 | ||||
| 			case 'form': // 13.13 <form:form>
 | ||||
| 			case 'dde-links': // 9.8 <table:dde-links>
 | ||||
| 			case 'annotation': // 14.1 <office:annotation>
 | ||||
| 				if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;} | ||||
| 				else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], false]); | ||||
| 				break; | ||||
| 
 | ||||
| 			case 'number-style': // 16.27.2 <number:number-style>
 | ||||
| 			case 'percentage-style': // 16.27.9 <number:percentage-style>
 | ||||
| 			case 'date-style': // 16.27.10 <number:date-style>
 | ||||
| 			case 'time-style': // 16.27.18 <number:time-style>
 | ||||
| 				if(Rn[1]==='/'){ | ||||
| 					number_format_map[NFtag.name] = NF; | ||||
| 					if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp; | ||||
| 				} else if(Rn[0].charAt(Rn[0].length-2) !== '/') { | ||||
| 					NF = ""; | ||||
| 					NFtag = parsexmltag(Rn[0], false); | ||||
| 					state.push([Rn[3], true]); | ||||
| 				} break; | ||||
| 
 | ||||
| 			case 'script': break; // 3.13 <office:script>
 | ||||
| 			case 'automatic-styles': break; // 3.15.3 <office:automatic-styles>
 | ||||
| 
 | ||||
| 			case 'style': break; // 16.2 <style:style>
 | ||||
| 			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': 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>
 | ||||
| 
 | ||||
| 			case 'number': // 16.27.3 <number:number>
 | ||||
| 				switch(state[state.length-1][0]) { | ||||
| 					case 'time-style': | ||||
| 					case 'date-style': | ||||
| 						tag = parsexmltag(Rn[0], false); | ||||
| 						NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break; | ||||
| 				} break; | ||||
| 
 | ||||
| 			case 'fraction': break; // TODO 16.27.6 <number:fraction>
 | ||||
| 
 | ||||
| 			case 'day': // 16.27.11 <number:day>
 | ||||
| 			case 'month': // 16.27.12 <number:month>
 | ||||
| 			case 'year': // 16.27.13 <number:year>
 | ||||
| 			case 'era': // 16.27.14 <number:era>
 | ||||
| 			case 'day-of-week': // 16.27.15 <number:day-of-week>
 | ||||
| 			case 'week-of-year': // 16.27.16 <number:week-of-year>
 | ||||
| 			case 'quarter': // 16.27.17 <number:quarter>
 | ||||
| 			case 'hours': // 16.27.19 <number:hours>
 | ||||
| 			case 'minutes': // 16.27.20 <number:minutes>
 | ||||
| 			case 'seconds': // 16.27.21 <number:seconds>
 | ||||
| 			case 'am-pm': // 16.27.22 <number:am-pm>
 | ||||
| 				switch(state[state.length-1][0]) { | ||||
| 					case 'time-style': | ||||
| 					case 'date-style': | ||||
| 						tag = parsexmltag(Rn[0], false); | ||||
| 						NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break; | ||||
| 				} break; | ||||
| 
 | ||||
| 			case 'boolean-style': break; // 16.27.23 <number:boolean-style>
 | ||||
| 			case 'boolean': break; // 16.27.24 <number:boolean>
 | ||||
| 			case 'text-style': break; // 16.27.25 <number:text-style>
 | ||||
| 			case 'text': // 16.27.26 <number:text>
 | ||||
| 				if(Rn[0].substr(-2) === "/>") break; | ||||
| 				else if(Rn[1]==="/") switch(state[state.length-1][0]) { | ||||
| 					case 'number-style': | ||||
| 					case 'date-style': | ||||
| 					case 'time-style': | ||||
| 						NF += str.slice(pidx, Rn.index); | ||||
| 						break; | ||||
| 				} | ||||
| 				else pidx = Rn.index + Rn[0].length; | ||||
| 				break; | ||||
| 			case 'text-content': break; // 16.27.27 <number:text-content>
 | ||||
| 			case 'text-properties': break; // 16.27.27 <style:text-properties>
 | ||||
| 
 | ||||
| 			case 'body': break; // 3.3 16.9.6 19.726.3
 | ||||
| 
 | ||||
| 			case 'forms': break; // 12.25.2 13.2
 | ||||
| 			case 'table-column': break; // 9.1.6 <table:table-column>
 | ||||
| 
 | ||||
| 			case 'null-date': break; // 9.4.2 <table:null-date> TODO: date1904
 | ||||
| 
 | ||||
| 			case 'graphic-properties': break; // 17.21 <style:graphic-properties>
 | ||||
| 			case 'calculation-settings': break; // 9.4.1 <table:calculation-settings>
 | ||||
| 			case 'named-expressions': break; // 9.4.11 <table:named-expressions>
 | ||||
| 			case 'named-range': break; // 9.4.12 <table:named-range>
 | ||||
| 			case 'named-expression': break; // 9.4.13 <table:named-expression>
 | ||||
| 			case 'sort': break; // 9.4.19 <table:sort>
 | ||||
| 			case 'sort-by': break; // 9.4.20 <table:sort-by>
 | ||||
| 			case 'sort-groups': break; // 9.4.22 <table:sort-groups>
 | ||||
| 
 | ||||
| 			case 'span': break; // <text:span>
 | ||||
| 			case 'line-break': break; // 6.1.5 <text:line-break>
 | ||||
| 			case 'p': | ||||
| 				if(Rn[1]==='/') textp = parse_text_p(str.slice(textpidx,Rn.index), textptag); | ||||
| 				else { textptag = parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; } | ||||
| 				break; // <text:p>
 | ||||
| 			case 's': break; // <text:s>
 | ||||
| 			case 'date': break; // <*:date>
 | ||||
| 
 | ||||
| 			case 'object': break; // 10.4.6.2 <draw:object>
 | ||||
| 			case 'title': break; // <*:title>
 | ||||
| 			case 'desc': break; // <*:desc>
 | ||||
| 
 | ||||
| 			case 'table-source': break; // 9.2.6
 | ||||
| 
 | ||||
| 			case 'iteration': break; // 9.4.3 <table:iteration>
 | ||||
| 			case 'content-validations': break; // 9.4.4 <table:
 | ||||
| 			case 'content-validation': break; // 9.4.5 <table:
 | ||||
| 			case 'error-message': break; // 9.4.7 <table:
 | ||||
| 			case 'database-ranges': break; // 9.4.14 <table:database-ranges>
 | ||||
| 			case 'database-range': break; // 9.4.15 <table:database-range>
 | ||||
| 			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 'list-level-style-bullet': break; // 16.31 <text:
 | ||||
| 			case 'list-level-style-number': break; // 16.32 <text:
 | ||||
| 			case 'list-level-properties': break; // 17.19 <style:
 | ||||
| 
 | ||||
| 			/* 7.3 Document Fields */ | ||||
| 			case 'sender-firstname': // 7.3.6.2
 | ||||
| 			case 'sender-lastname': // 7.3.6.3
 | ||||
| 			case 'sender-initials': // 7.3.6.4
 | ||||
| 			case 'sender-title': // 7.3.6.5
 | ||||
| 			case 'sender-position': // 7.3.6.6
 | ||||
| 			case 'sender-email': // 7.3.6.7
 | ||||
| 			case 'sender-phone-private': // 7.3.6.8
 | ||||
| 			case 'sender-fax': // 7.3.6.9
 | ||||
| 			case 'sender-company': // 7.3.6.10
 | ||||
| 			case 'sender-phone-work': // 7.3.6.11
 | ||||
| 			case 'sender-street': // 7.3.6.12
 | ||||
| 			case 'sender-city': // 7.3.6.13
 | ||||
| 			case 'sender-postal-code': // 7.3.6.14
 | ||||
| 			case 'sender-country': // 7.3.6.15
 | ||||
| 			case 'sender-state-or-province': // 7.3.6.16
 | ||||
| 			case 'author-name': // 7.3.7.1
 | ||||
| 			case 'author-initials': // 7.3.7.2
 | ||||
| 			case 'chapter': // 7.3.8
 | ||||
| 			case 'file-name': // 7.3.9
 | ||||
| 			case 'template-name': // 7.3.9
 | ||||
| 			case 'sheet-name': // 7.3.9
 | ||||
| 				break; | ||||
| 
 | ||||
| 			/* 9.6 Data Pilot Tables <table: */ | ||||
| 			case 'data-pilot-table': // 9.6.3
 | ||||
| 			case 'source-cell-range': // 9.6.5
 | ||||
| 			case 'source-service': // 9.6.6
 | ||||
| 			case 'data-pilot-field': // 9.6.7
 | ||||
| 			case 'data-pilot-level': // 9.6.8
 | ||||
| 			case 'data-pilot-subtotals': // 9.6.9
 | ||||
| 			case 'data-pilot-subtotal': // 9.6.10
 | ||||
| 			case 'data-pilot-members': // 9.6.11
 | ||||
| 			case 'data-pilot-member': // 9.6.12
 | ||||
| 			case 'data-pilot-display-info': // 9.6.13
 | ||||
| 			case 'data-pilot-sort-info': // 9.6.14
 | ||||
| 			case 'data-pilot-layout-info': // 9.6.15
 | ||||
| 			case 'data-pilot-field-reference': // 9.6.16
 | ||||
| 			case 'data-pilot-groups': // 9.6.17
 | ||||
| 			case 'data-pilot-group': // 9.6.18
 | ||||
| 			case 'data-pilot-group-member': // 9.6.19
 | ||||
| 				break; | ||||
| 
 | ||||
| 			/* 10.3 Drawing Shapes */ | ||||
| 			case 'rect': // 10.3.2
 | ||||
| 				break; | ||||
| 
 | ||||
| 			/* 14.6 DDE Connections */ | ||||
| 			case 'dde-connection-decls': // 14.6.2 <text:
 | ||||
| 			case 'dde-connection-decl': // 14.6.3 <text:
 | ||||
| 			case 'dde-link': // 14.6.4 <table:
 | ||||
| 			case 'dde-source': // 14.6.5 <office:
 | ||||
| 				break; | ||||
| 
 | ||||
| 			case 'properties': break; // 13.7 <form:properties>
 | ||||
| 			case 'property': break; // 13.8 <form:property>
 | ||||
| 
 | ||||
| 			case 'a': break; // 6.1.8 hyperlink
 | ||||
| 
 | ||||
| 			/* non-standard */ | ||||
| 			case 'table-protection': break; | ||||
| 			case 'data-pilot-grand-total': break; // <table:
 | ||||
| 			default: | ||||
| 				if(Rn[2] === 'dc:') break; // TODO: properties
 | ||||
| 				if(Rn[2] === 'draw:') break; // TODO: drawing
 | ||||
| 				if(Rn[2] === 'calcext:') break; // ignore undocumented extensions
 | ||||
| 				if(opts.WTF) throw Rn; | ||||
| 		} | ||||
| 		var out = { | ||||
| 			Sheets: Sheets, | ||||
| 			SheetNames: SheetNames | ||||
| 		}; | ||||
| 		return out; | ||||
| 	}; | ||||
| })(); | ||||
| var write_content_xml/*:{(wb:any, opts:any):string}*/ = (function() { | ||||
| 	var null_cell_xml = '          <table:table-cell />\n'; | ||||
| 	var write_ws = function(ws, wb, i/*:number*/, opts)/*:string*/ { | ||||
| 		/* Section 9 Tables */ | ||||
| 		var o = []; | ||||
| 		o.push('      <table:table table:name="' + escapexml(wb.SheetNames[i]) + '">\n'); | ||||
| 		var R=0,C=0, range = get_utils().decode_range(ws['!ref']); | ||||
| 		for(R = 0; R < range.s.r; ++R) o.push('        <table:table-row></table:table-row>\n'); | ||||
| 		for(; R <= range.e.r; ++R) { | ||||
| 			o.push('        <table:table-row>\n'); | ||||
| 			for(C=0; C < range.s.c; ++C) o.push(null_cell_xml); | ||||
| 			for(; C <= range.e.c; ++C) { | ||||
| 				var ref = get_utils().encode_cell({r:R, c:C}), cell = ws[ref]; | ||||
| 				if(cell) switch(cell.t) { | ||||
| 					case 'b': o.push('          <table:table-cell office:value-type="boolean" office:boolean-value="' + (cell.v ? 'true' : 'false') + '"><text:p>' + (cell.v ? 'TRUE' : 'FALSE') + '</text:p></table:table-cell>\n'); break; | ||||
| 					case 'n': o.push('          <table:table-cell office:value-type="float" office:value="' + cell.v + '"><text:p>' + (cell.w||cell.v) + '</text:p></table:table-cell>\n'); break; | ||||
| 					case 's': case 'str': o.push('          <table:table-cell office:value-type="string"><text:p>' + escapexml(cell.v) + '</text:p></table:table-cell>\n'); break; | ||||
| 					//case 'd': // TODO
 | ||||
| 					//case 'e':
 | ||||
| 					default: o.push(null_cell_xml); | ||||
| 				} else o.push(null_cell_xml); | ||||
| 			} | ||||
| 			o.push('        </table:table-row>\n'); | ||||
| 		} | ||||
| 		o.push('      </table:table>\n'); | ||||
| 		return o.join(""); | ||||
| 	}; | ||||
| 
 | ||||
| 	return function wcx(wb, opts) { | ||||
| 		var o = [XML_HEADER]; | ||||
| 		/* 3.1.3.2 */ | ||||
| 		o.push('<office:document-content office:version="1.2" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0">\n'); // TODO
 | ||||
| 		o.push('  <office:body>\n'); | ||||
| 		o.push('    <office:spreadsheet>\n'); | ||||
| 		for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts)); | ||||
| 		o.push('    </office:spreadsheet>\n'); | ||||
| 		o.push('  </office:body>\n'); | ||||
| 		o.push('</office:document-content>'); | ||||
| 		return o.join(""); | ||||
| 	}; | ||||
| })(); | ||||
| /* Part 3: Packages */ | ||||
| function parse_ods(zip/*:ZIPFile*/, opts/*:?ParseOpts*/) { | ||||
| 	opts = opts || ({}/*:any*/); | ||||
| 	var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts); | ||||
| 	return parse_content_xml(getzipdata(zip, 'content.xml'), opts); | ||||
| } | ||||
| function write_ods(wb/*:any*/, opts/*:any*/) { | ||||
| 	/*:: if(!jszip) throw new Error("JSZip is not available"); */ | ||||
| 	var zip = new jszip(); | ||||
| 	var f = ""; | ||||
| 
 | ||||
| 	var manifest/*:Array<Array<string> >*/ = []; | ||||
| 	var rdf = []; | ||||
| 
 | ||||
| 	/* 3:3.3 and 2:2.2.4 */ | ||||
| 	f = "mimetype"; | ||||
| 	zip.file(f, "application/vnd.oasis.opendocument.spreadsheet"); | ||||
| 
 | ||||
| 	/* Part 2 Section 2.2 Documents */ | ||||
| 	f = "content.xml"; | ||||
| 	zip.file(f, write_content_xml(wb, opts)); | ||||
| 	manifest.push([f, "text/xml"]); | ||||
| 	rdf.push([f, "ContentFile"]); | ||||
| 
 | ||||
| 	/* Part 3 Section 6 Metadata Manifest File */ | ||||
| 	f = "manifest.rdf"; | ||||
| 	zip.file(f, write_rdf(rdf, opts)); | ||||
| 	manifest.push([f, "application/rdf+xml"]); | ||||
| 
 | ||||
| 	/* Part 3 Section 4 Manifest File */ | ||||
| 	f = "META-INF/manifest.xml"; | ||||
| 	zip.file(f, write_manifest(manifest, opts)); | ||||
| 
 | ||||
| 	return zip; | ||||
| } | ||||
| ODS.parse_ods = parse_ods; | ||||
| ODS.write_ods = write_ods; | ||||
| })(typeof exports !== 'undefined' ? exports : ODS); | ||||
							
								
								
									
										287
									
								
								ods.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										287
									
								
								ods.js
									
									
									
									
									
								
							| @ -21,6 +21,14 @@ function cc2str(arr) { | ||||
| 	for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]); | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| function dup(o) { | ||||
| 	if(typeof JSON != 'undefined') return JSON.parse(JSON.stringify(o)); | ||||
| 	if(typeof o != 'object' || !o) return o; | ||||
| 	var out = {}; | ||||
| 	for(var k in o) if(o.hasOwnProperty(k)) out[k] = dup(o[k]); | ||||
| 	return out; | ||||
| } | ||||
| function getdata(data) { | ||||
| 	if(!data) return null; | ||||
| 	if(data.data) return data.data; | ||||
| @ -67,7 +75,7 @@ function parsexmltag(tag, skip_root) { | ||||
| 	for(; eq !== tag.length; ++eq) if((c = tag.charCodeAt(eq)) === 32 || c === 10 || c === 13) break; | ||||
| 	if(!skip_root) z[0] = tag.substr(0, eq); | ||||
| 	if(eq === tag.length) return z; | ||||
| 	var m = tag.match(attregexg), j=0, w="", v="", i=0, q="", cc=""; | ||||
| 	var m = tag.match(attregexg), j=0, v="", i=0, q="", cc=""; | ||||
| 	if(m) for(i = 0; i != m.length; ++i) { | ||||
| 		cc = m[i]; | ||||
| 		for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break; | ||||
| @ -108,7 +116,7 @@ function escapexml(text){ | ||||
| 	return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).substr(-4) + "_";}); | ||||
| } | ||||
| 
 | ||||
| function parsexmlbool(value, tag) { | ||||
| function parsexmlbool(value) { | ||||
| 	switch(value) { | ||||
| 		case '1': case 'true': case 'TRUE': return true; | ||||
| 		/* case '0': case 'false': case 'FALSE':*/ | ||||
| @ -147,6 +155,8 @@ function parse_isodur(s) { | ||||
| 	} | ||||
| 	return sec; | ||||
| } | ||||
| 
 | ||||
| var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n'; | ||||
| /* copied from js-xls (C) SheetJS Apache2 license */ | ||||
| function xlml_normalize(d) { | ||||
| 	if(has_buf && Buffer.isBuffer(d)) return d.toString('utf8'); | ||||
| @ -157,14 +167,14 @@ function xlml_normalize(d) { | ||||
| var xlmlregex = /<(\/?)([a-z0-9]*:|)([\w-]+)[^>]*>/mg; | ||||
| /* Part 3 Section 4 Manifest File */ | ||||
| var CT_ODS = "application/vnd.oasis.opendocument.spreadsheet"; | ||||
| var parse_manifest = function(d, opts) { | ||||
| function parse_manifest(d, opts) { | ||||
| 	var str = xlml_normalize(d); | ||||
| 	var Rn; | ||||
| 	var FEtag; | ||||
| 	while((Rn = xlmlregex.exec(str))) switch(Rn[3]) { | ||||
| 		case 'manifest': break; // 4.2 <manifest:manifest>
 | ||||
| 		case 'file-entry': // 4.3 <manifest:file-entry>
 | ||||
| 			FEtag = parsexmltag(Rn[0]); | ||||
| 			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>
 | ||||
| @ -172,11 +182,46 @@ var parse_manifest = function(d, opts) { | ||||
| 		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: throw Rn; | ||||
| 		default: if(opts && opts.WTF) throw Rn; | ||||
| 	} | ||||
| }; | ||||
| } | ||||
| 
 | ||||
| function write_manifest(manifest, opts) { | ||||
| 	var o = [XML_HEADER]; | ||||
| 	o.push('<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2">\n'); | ||||
| 	o.push('  <manifest:file-entry manifest:full-path="/" manifest:version="1.2" manifest:media-type="application/vnd.oasis.opendocument.spreadsheet"/>\n'); | ||||
| 	for(var i = 0; i < manifest.length; ++i) o.push('  <manifest:file-entry manifest:full-path="' + manifest[i][0] + '" manifest:media-type="' + manifest[i][1] + '"/>\n'); | ||||
| 	o.push('</manifest:manifest>'); | ||||
| 	return o.join(""); | ||||
| } | ||||
| /* Part 3 Section 6 Metadata Manifest File */ | ||||
| function write_rdf_type(file, res, tag) { | ||||
| 	return [ | ||||
| 		'  <rdf:Description rdf:about="' + file + '">\n', | ||||
| 		'    <rdf:type rdf:resource="http://docs.oasis-open.org/ns/office/1.2/meta/' + (tag || "odf") + '#' + res + '"/>\n', | ||||
| 		'  </rdf:Description>\n' | ||||
| 	].join(""); | ||||
| } | ||||
| function write_rdf_has(base, file) { | ||||
| 	return [ | ||||
| 		'  <rdf:Description rdf:about="' + base + '">\n', | ||||
| 		'    <ns0:hasPart xmlns:ns0="http://docs.oasis-open.org/ns/office/1.2/meta/pkg#" rdf:resource="' + file + '"/>\n', | ||||
| 		'  </rdf:Description>\n' | ||||
| 	].join(""); | ||||
| } | ||||
| function write_rdf(rdf, opts) { | ||||
| 	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 parse_text_p = function(text, tag) { | ||||
| 	return utf8read(text.replace(/<text:s\/>/g," ").replace(/<[^>]*>/g,"")); | ||||
| 	return unescapexml(utf8read(text.replace(/<text:s\/>/g," ").replace(/<[^>]*>/g,""))); | ||||
| }; | ||||
| 
 | ||||
| var utf8read = function utf8reada(orig) { | ||||
| @ -213,27 +258,29 @@ var parse_content_xml = (function() { | ||||
| 		var str = xlml_normalize(d); | ||||
| 		var state = [], tmp; | ||||
| 		var tag; | ||||
| 		var NFtag, NF, pidx; | ||||
| 		var NFtag = {name:""}, NF = "", pidx = 0; | ||||
| 		var sheetag; | ||||
| 		var Sheets = {}, SheetNames = [], ws = {}; | ||||
| 		var Rn, q; | ||||
| 		var ctag; | ||||
| 		var textp, textpidx, textptag; | ||||
| 		var R, C, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}}; | ||||
| 		var ctag = {value:""}; | ||||
| 		var textp = "", textpidx = 0, textptag; | ||||
| 		var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}}; | ||||
| 		var number_format_map = {}; | ||||
| 		var merges = [], mrange = {}, mR = 0, mC = 0; | ||||
| 
 | ||||
| 		var rept = 1; | ||||
| 		xlmlregex.lastIndex = 0; | ||||
| 		while((Rn = xlmlregex.exec(str))) switch(Rn[3]) { | ||||
| 
 | ||||
| 			case 'table': // 9.1.2 <table:table>
 | ||||
| 				if(Rn[1]==='/') { | ||||
| 					if(range.e.c >= range.s.c && range.e.r >= range.s.r) ws['!ref'] = get_utils().encode_range(range); | ||||
| 					if(merges.length) ws['!merges'] = merges; | ||||
| 					sheetag.name = utf8read(sheetag.name); | ||||
| 					SheetNames.push(sheetag.name); | ||||
| 					Sheets[sheetag.name] = ws; | ||||
| 				} | ||||
| 				else if(Rn[0].charAt(Rn[0].length-2) !== '/') { | ||||
| 					sheetag = parsexmltag(Rn[0]); | ||||
| 					sheetag = parsexmltag(Rn[0], false); | ||||
| 					R = C = -1; | ||||
| 					range.s.r = range.s.c = 10000000; range.e.r = range.e.c = 0; | ||||
| 					ws = {}; merges = []; | ||||
| @ -247,17 +294,18 @@ var parse_content_xml = (function() { | ||||
| 				++C; break; /* stub */ | ||||
| 			case 'table-cell': | ||||
| 				if(Rn[0].charAt(Rn[0].length-2) === '/') { | ||||
| 					ctag = parsexmltag(Rn[0]); | ||||
| 					ctag = parsexmltag(Rn[0], false); | ||||
| 					if(ctag['number-columns-repeated']) C+= parseInt(ctag['number-columns-repeated'], 10); | ||||
| 					else ++C; | ||||
| 				} | ||||
| 				else if(Rn[1]!=='/') { | ||||
| 					++C; | ||||
| 					rept = 1; | ||||
| 					if(C > range.e.c) range.e.c = C; | ||||
| 					if(R > range.e.r) range.e.r = R; | ||||
| 					if(C < range.s.c) range.s.c = C; | ||||
| 					if(R < range.s.r) range.s.r = R; | ||||
| 					ctag = parsexmltag(Rn[0]); | ||||
| 					ctag = parsexmltag(Rn[0], false); | ||||
| 					q = {t:ctag['value-type'], v:null}; | ||||
| 					if(ctag['number-columns-spanned'] || ctag['number-rows-spanned']) { | ||||
| 						mR = parseInt(ctag['number-rows-spanned'],10) || 0; | ||||
| @ -265,6 +313,10 @@ var parse_content_xml = (function() { | ||||
| 						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']) rept = parseInt(ctag['number-columns-repeated'], 10); | ||||
| 
 | ||||
| 					/* 19.385 office:value-type */ | ||||
| 					switch(q.t) { | ||||
| 						case 'boolean': q.t = 'b'; q.v = parsexmlbool(ctag['boolean-value']); break; | ||||
| @ -273,14 +325,22 @@ var parse_content_xml = (function() { | ||||
| 						case 'currency': q.t = 'n'; q.v = parseFloat(ctag.value); break; | ||||
| 						case 'date': q.t = 'n'; q.v = datenum(ctag['date-value']); q.z = 'm/d/yy'; break; | ||||
| 						case 'time': q.t = 'n'; q.v = parse_isodur(ctag['time-value'])/86400; break; | ||||
| 						case 'string': q.t = 's'; break; | ||||
| 						default: throw new Error('Unsupported value type ' + q.t); | ||||
| 						default: | ||||
| 							if(q.t === 'string' || !q.t) { | ||||
| 								q.t = 's'; | ||||
| 								if(ctag['string-value'] != null) textp = ctag['string-value']; | ||||
| 							} else throw new Error('Unsupported value type ' + q.t); | ||||
| 					} | ||||
| 				} else { | ||||
| 					if(q.t === 's') q.v = textp; | ||||
| 					if(q.t === 's') q.v = textp || ''; | ||||
| 					if(textp) q.w = textp; | ||||
| 					if(!(opts.sheetRows && opts.sheetRows < R)) ws[get_utils().encode_cell({r:R,c:C})] = q; | ||||
| 					q = null; | ||||
| 					if(!(opts.sheetRows && opts.sheetRows < R)) { | ||||
| 						ws[get_utils().encode_cell({r:R,c:C})] = q; | ||||
| 						while(--rept > 0) ws[get_utils().encode_cell({r:R,c:++C})] = dup(q); | ||||
| 						if(range.e.c <= C) range.e.c = C; | ||||
| 					} | ||||
| 					q = {}; | ||||
| 					textp = ""; | ||||
| 				} | ||||
| 				break; // 9.1.4 <table:table-cell>
 | ||||
| 
 | ||||
| @ -296,6 +356,13 @@ var parse_content_xml = (function() { | ||||
| 			/* ignore state */ | ||||
| 			case 'shapes': // 9.2.8 <table:shapes>
 | ||||
| 			case 'frame': // 10.4.2 <draw:frame>
 | ||||
| 			case 'text-box': // 10.4.3 <draw:text-box>
 | ||||
| 			case 'image': // 10.4.4 <draw:image>
 | ||||
| 			case 'data-pilot-tables': // 9.6.2 <table:data-pilot-tables>
 | ||||
| 			case 'list-style': // 16.30 <text:list-style>
 | ||||
| 			case 'form': // 13.13 <form:form>
 | ||||
| 			case 'dde-links': // 9.8 <table:dde-links>
 | ||||
| 			case 'annotation': // 14.1 <office:annotation>
 | ||||
| 				if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;} | ||||
| 				else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], false]); | ||||
| 				break; | ||||
| @ -309,7 +376,7 @@ var parse_content_xml = (function() { | ||||
| 					if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp; | ||||
| 				} else if(Rn[0].charAt(Rn[0].length-2) !== '/') { | ||||
| 					NF = ""; | ||||
| 					NFtag = parsexmltag(Rn[0]); | ||||
| 					NFtag = parsexmltag(Rn[0], false); | ||||
| 					state.push([Rn[3], true]); | ||||
| 				} break; | ||||
| 
 | ||||
| @ -317,6 +384,7 @@ var parse_content_xml = (function() { | ||||
| 			case 'automatic-styles': break; // 3.15.3 <office:automatic-styles>
 | ||||
| 
 | ||||
| 			case 'style': break; // 16.2 <style:style>
 | ||||
| 			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>
 | ||||
| @ -329,10 +397,12 @@ var parse_content_xml = (function() { | ||||
| 				switch(state[state.length-1][0]) { | ||||
| 					case 'time-style': | ||||
| 					case 'date-style': | ||||
| 						tag = parsexmltag(Rn[0]); | ||||
| 						tag = parsexmltag(Rn[0], false); | ||||
| 						NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break; | ||||
| 				} break; | ||||
| 
 | ||||
| 			case 'fraction': break; // TODO 16.27.6 <number:fraction>
 | ||||
| 
 | ||||
| 			case 'day': // 16.27.11 <number:day>
 | ||||
| 			case 'month': // 16.27.12 <number:month>
 | ||||
| 			case 'year': // 16.27.13 <number:year>
 | ||||
| @ -347,7 +417,7 @@ var parse_content_xml = (function() { | ||||
| 				switch(state[state.length-1][0]) { | ||||
| 					case 'time-style': | ||||
| 					case 'date-style': | ||||
| 						tag = parsexmltag(Rn[0]); | ||||
| 						tag = parsexmltag(Rn[0], false); | ||||
| 						NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break; | ||||
| 				} break; | ||||
| 
 | ||||
| @ -373,30 +443,114 @@ var parse_content_xml = (function() { | ||||
| 			case 'forms': break; // 12.25.2 13.2
 | ||||
| 			case 'table-column': break; // 9.1.6 <table:table-column>
 | ||||
| 
 | ||||
| 			case 'graphic-properties': break; | ||||
| 			case 'null-date': break; // 9.4.2 <table:null-date> TODO: date1904
 | ||||
| 
 | ||||
| 			case 'graphic-properties': break; // 17.21 <style:graphic-properties>
 | ||||
| 			case 'calculation-settings': break; // 9.4.1 <table:calculation-settings>
 | ||||
| 			case 'named-expressions': break; // 9.4.11 <table:named-expressions>
 | ||||
| 			case 'named-range': break; // 9.4.11 <table:named-range>
 | ||||
| 			case 'named-range': break; // 9.4.12 <table:named-range>
 | ||||
| 			case 'named-expression': break; // 9.4.13 <table:named-expression>
 | ||||
| 			case 'sort': break; // 9.4.19 <table:sort>
 | ||||
| 			case 'sort-by': break; // 9.4.20 <table:sort-by>
 | ||||
| 			case 'sort-groups': break; // 9.4.22 <table:sort-groups>
 | ||||
| 
 | ||||
| 			case 'span': break; // <text:span>
 | ||||
| 			case 'line-break': break; // 6.1.5 <text:line-break>
 | ||||
| 			case 'p': | ||||
| 				if(Rn[1]==='/') textp = parse_text_p(str.slice(textpidx,Rn.index), textptag); | ||||
| 				else { textptag = parsexmltag(Rn[0]); textpidx = Rn.index + Rn[0].length; } | ||||
| 				else { textptag = parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; } | ||||
| 				break; // <text:p>
 | ||||
| 			case 's': break; // <text:s>
 | ||||
| 			case 'date': break; // <*:date>
 | ||||
| 			case 'annotation': break; | ||||
| 
 | ||||
| 			case 'object': break; // 10.4.6.2 <draw:object>
 | ||||
| 			case 'title': break; // <*:title>
 | ||||
| 			case 'desc': break; // <*:desc>
 | ||||
| 
 | ||||
| 			case 'table-source': break; // 9.2.6
 | ||||
| 
 | ||||
| 			case 'iteration': break; // 9.4.3 <table:iteration>
 | ||||
| 			case 'content-validations': break; // 9.4.4 <table:
 | ||||
| 			case 'content-validation': break; // 9.4.5 <table:
 | ||||
| 			case 'error-message': break; // 9.4.7 <table:
 | ||||
| 			case 'database-ranges': break; // 9.4.14 <table:database-ranges>
 | ||||
| 			case 'database-range': break; // 9.4.15 <table:database-range>
 | ||||
| 			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>
 | ||||
| 			default: if(opts.WTF) throw Rn; | ||||
| 
 | ||||
| 			case 'list-level-style-bullet': break; // 16.31 <text:
 | ||||
| 			case 'list-level-style-number': break; // 16.32 <text:
 | ||||
| 			case 'list-level-properties': break; // 17.19 <style:
 | ||||
| 
 | ||||
| 			/* 7.3 Document Fields */ | ||||
| 			case 'sender-firstname': // 7.3.6.2
 | ||||
| 			case 'sender-lastname': // 7.3.6.3
 | ||||
| 			case 'sender-initials': // 7.3.6.4
 | ||||
| 			case 'sender-title': // 7.3.6.5
 | ||||
| 			case 'sender-position': // 7.3.6.6
 | ||||
| 			case 'sender-email': // 7.3.6.7
 | ||||
| 			case 'sender-phone-private': // 7.3.6.8
 | ||||
| 			case 'sender-fax': // 7.3.6.9
 | ||||
| 			case 'sender-company': // 7.3.6.10
 | ||||
| 			case 'sender-phone-work': // 7.3.6.11
 | ||||
| 			case 'sender-street': // 7.3.6.12
 | ||||
| 			case 'sender-city': // 7.3.6.13
 | ||||
| 			case 'sender-postal-code': // 7.3.6.14
 | ||||
| 			case 'sender-country': // 7.3.6.15
 | ||||
| 			case 'sender-state-or-province': // 7.3.6.16
 | ||||
| 			case 'author-name': // 7.3.7.1
 | ||||
| 			case 'author-initials': // 7.3.7.2
 | ||||
| 			case 'chapter': // 7.3.8
 | ||||
| 			case 'file-name': // 7.3.9
 | ||||
| 			case 'template-name': // 7.3.9
 | ||||
| 			case 'sheet-name': // 7.3.9
 | ||||
| 				break; | ||||
| 
 | ||||
| 			/* 9.6 Data Pilot Tables <table: */ | ||||
| 			case 'data-pilot-table': // 9.6.3
 | ||||
| 			case 'source-cell-range': // 9.6.5
 | ||||
| 			case 'source-service': // 9.6.6
 | ||||
| 			case 'data-pilot-field': // 9.6.7
 | ||||
| 			case 'data-pilot-level': // 9.6.8
 | ||||
| 			case 'data-pilot-subtotals': // 9.6.9
 | ||||
| 			case 'data-pilot-subtotal': // 9.6.10
 | ||||
| 			case 'data-pilot-members': // 9.6.11
 | ||||
| 			case 'data-pilot-member': // 9.6.12
 | ||||
| 			case 'data-pilot-display-info': // 9.6.13
 | ||||
| 			case 'data-pilot-sort-info': // 9.6.14
 | ||||
| 			case 'data-pilot-layout-info': // 9.6.15
 | ||||
| 			case 'data-pilot-field-reference': // 9.6.16
 | ||||
| 			case 'data-pilot-groups': // 9.6.17
 | ||||
| 			case 'data-pilot-group': // 9.6.18
 | ||||
| 			case 'data-pilot-group-member': // 9.6.19
 | ||||
| 				break; | ||||
| 
 | ||||
| 			/* 10.3 Drawing Shapes */ | ||||
| 			case 'rect': // 10.3.2
 | ||||
| 				break; | ||||
| 
 | ||||
| 			/* 14.6 DDE Connections */ | ||||
| 			case 'dde-connection-decls': // 14.6.2 <text:
 | ||||
| 			case 'dde-connection-decl': // 14.6.3 <text:
 | ||||
| 			case 'dde-link': // 14.6.4 <table:
 | ||||
| 			case 'dde-source': // 14.6.5 <office:
 | ||||
| 				break; | ||||
| 
 | ||||
| 			case 'properties': break; // 13.7 <form:properties>
 | ||||
| 			case 'property': break; // 13.8 <form:property>
 | ||||
| 
 | ||||
| 			case 'a': break; // 6.1.8 hyperlink
 | ||||
| 
 | ||||
| 			/* non-standard */ | ||||
| 			case 'table-protection': break; | ||||
| 			case 'data-pilot-grand-total': break; // <table:
 | ||||
| 			default: | ||||
| 				if(Rn[2] === 'dc:') break; // TODO: properties
 | ||||
| 				if(Rn[2] === 'draw:') break; // TODO: drawing
 | ||||
| 				if(Rn[2] === 'calcext:') break; // ignore undocumented extensions
 | ||||
| 				if(opts.WTF) throw Rn; | ||||
| 		} | ||||
| 		var out = { | ||||
| 			Sheets: Sheets, | ||||
| @ -405,10 +559,81 @@ var parse_content_xml = (function() { | ||||
| 		return out; | ||||
| 	}; | ||||
| })(); | ||||
| var write_content_xml = (function() { | ||||
| 	var null_cell_xml = '          <table:table-cell />\n'; | ||||
| 	var write_ws = function(ws, wb, i, opts) { | ||||
| 		/* Section 9 Tables */ | ||||
| 		var o = []; | ||||
| 		o.push('      <table:table table:name="' + escapexml(wb.SheetNames[i]) + '">\n'); | ||||
| 		var R=0,C=0, range = get_utils().decode_range(ws['!ref']); | ||||
| 		for(R = 0; R < range.s.r; ++R) o.push('        <table:table-row></table:table-row>\n'); | ||||
| 		for(; R <= range.e.r; ++R) { | ||||
| 			o.push('        <table:table-row>\n'); | ||||
| 			for(C=0; C < range.s.c; ++C) o.push(null_cell_xml); | ||||
| 			for(; C <= range.e.c; ++C) { | ||||
| 				var ref = get_utils().encode_cell({r:R, c:C}), cell = ws[ref]; | ||||
| 				if(cell) switch(cell.t) { | ||||
| 					case 'b': o.push('          <table:table-cell office:value-type="boolean" office:boolean-value="' + (cell.v ? 'true' : 'false') + '"><text:p>' + (cell.v ? 'TRUE' : 'FALSE') + '</text:p></table:table-cell>\n'); break; | ||||
| 					case 'n': o.push('          <table:table-cell office:value-type="float" office:value="' + cell.v + '"><text:p>' + (cell.w||cell.v) + '</text:p></table:table-cell>\n'); break; | ||||
| 					case 's': case 'str': o.push('          <table:table-cell office:value-type="string"><text:p>' + escapexml(cell.v) + '</text:p></table:table-cell>\n'); break; | ||||
| 					//case 'd': // TODO
 | ||||
| 					//case 'e':
 | ||||
| 					default: o.push(null_cell_xml); | ||||
| 				} else o.push(null_cell_xml); | ||||
| 			} | ||||
| 			o.push('        </table:table-row>\n'); | ||||
| 		} | ||||
| 		o.push('      </table:table>\n'); | ||||
| 		return o.join(""); | ||||
| 	}; | ||||
| 
 | ||||
| 	return function wcx(wb, opts) { | ||||
| 		var o = [XML_HEADER]; | ||||
| 		/* 3.1.3.2 */ | ||||
| 		o.push('<office:document-content office:version="1.2" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0">\n'); // TODO
 | ||||
| 		o.push('  <office:body>\n'); | ||||
| 		o.push('    <office:spreadsheet>\n'); | ||||
| 		for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts)); | ||||
| 		o.push('    </office:spreadsheet>\n'); | ||||
| 		o.push('  </office:body>\n'); | ||||
| 		o.push('</office:document-content>'); | ||||
| 		return o.join(""); | ||||
| 	}; | ||||
| })(); | ||||
| /* Part 3: Packages */ | ||||
| var parse_ods = function(zip, opts) { | ||||
| 	//var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'));
 | ||||
| function parse_ods(zip, opts) { | ||||
| 	opts = opts || ({}); | ||||
| 	var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts); | ||||
| 	return parse_content_xml(getzipdata(zip, 'content.xml'), opts); | ||||
| }; | ||||
| } | ||||
| function write_ods(wb, opts) { | ||||
| var zip = new jszip(); | ||||
| 	var f = ""; | ||||
| 
 | ||||
| 	var manifest = []; | ||||
| 	var rdf = []; | ||||
| 
 | ||||
| 	/* 3:3.3 and 2:2.2.4 */ | ||||
| 	f = "mimetype"; | ||||
| 	zip.file(f, "application/vnd.oasis.opendocument.spreadsheet"); | ||||
| 
 | ||||
| 	/* Part 2 Section 2.2 Documents */ | ||||
| 	f = "content.xml"; | ||||
| 	zip.file(f, write_content_xml(wb, opts)); | ||||
| 	manifest.push([f, "text/xml"]); | ||||
| 	rdf.push([f, "ContentFile"]); | ||||
| 
 | ||||
| 	/* Part 3 Section 6 Metadata Manifest File */ | ||||
| 	f = "manifest.rdf"; | ||||
| 	zip.file(f, write_rdf(rdf, opts)); | ||||
| 	manifest.push([f, "application/rdf+xml"]); | ||||
| 
 | ||||
| 	/* Part 3 Section 4 Manifest File */ | ||||
| 	f = "META-INF/manifest.xml"; | ||||
| 	zip.file(f, write_manifest(manifest, opts)); | ||||
| 
 | ||||
| 	return zip; | ||||
| } | ||||
| ODS.parse_ods = parse_ods; | ||||
| ODS.write_ods = write_ods; | ||||
| })(typeof exports !== 'undefined' ? exports : ODS); | ||||
|  | ||||
							
								
								
									
										1
									
								
								odsbits/.npmignore
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										1
									
								
								odsbits/.npmignore
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| *.js | ||||
| @ -1,3 +1,4 @@ | ||||
| /*:: declare var XLSX: any; */ | ||||
| var get_utils = function() { | ||||
| 	if(typeof XLSX !== 'undefined') return XLSX.utils; | ||||
| 	if(typeof module !== "undefined" && typeof require !== 'undefined') try { | ||||
|  | ||||
| @ -5,3 +5,11 @@ function cc2str(arr) { | ||||
| 	for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]); | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| function dup(o/*:object*/)/*:object*/ { | ||||
| 	if(typeof JSON != 'undefined') return JSON.parse(JSON.stringify(o)); | ||||
| 	if(typeof o != 'object' || !o) return o; | ||||
| 	var out = {}; | ||||
| 	for(var k in o) if(o.hasOwnProperty(k)) out[k] = dup(o[k]); | ||||
| 	return out; | ||||
| } | ||||
|  | ||||
| @ -20,13 +20,14 @@ function getzipfile(zip, file) { | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| function getzipdata(zip, file, safe) { | ||||
| function getzipdata(zip, file, safe/*:?boolean*/) { | ||||
| 	if(!safe) return getdata(getzipfile(zip, file)); | ||||
| 	if(!file) return null; | ||||
| 	try { return getzipdata(zip, file); } catch(e) { return null; } | ||||
| } | ||||
| 
 | ||||
| var _fs, jszip; | ||||
| /*:: declare var JSZip:any; */ | ||||
| if(typeof JSZip !== 'undefined') jszip = JSZip; | ||||
| if (typeof exports !== 'undefined') { | ||||
| 	if (typeof module !== 'undefined' && module.exports) { | ||||
|  | ||||
| @ -2,12 +2,12 @@ var attregexg=/\b[\w:-]+=["'][^"]*['"]/g; | ||||
| var tagregex=/<[^>]*>/g; | ||||
| var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/; | ||||
| function parsexmltag(tag, skip_root) { | ||||
| 	var z = []; | ||||
| 	var z/*:any*/ = []; | ||||
| 	var eq = 0, c = 0; | ||||
| 	for(; eq !== tag.length; ++eq) if((c = tag.charCodeAt(eq)) === 32 || c === 10 || c === 13) break; | ||||
| 	if(!skip_root) z[0] = tag.substr(0, eq); | ||||
| 	if(eq === tag.length) return z; | ||||
| 	var m = tag.match(attregexg), j=0, w="", v="", i=0, q="", cc=""; | ||||
| 	var m = tag.match(attregexg), j=0, v="", i=0, q="", cc=""; | ||||
| 	if(m) for(i = 0; i != m.length; ++i) { | ||||
| 		cc = m[i]; | ||||
| 		for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break; | ||||
| @ -48,7 +48,7 @@ function escapexml(text){ | ||||
| 	return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).substr(-4) + "_";}); | ||||
| } | ||||
| 
 | ||||
| function parsexmlbool(value, tag) { | ||||
| function parsexmlbool(value) { | ||||
| 	switch(value) { | ||||
| 		case '1': case 'true': case 'TRUE': return true; | ||||
| 		/* case '0': case 'false': case 'FALSE':*/ | ||||
| @ -87,3 +87,5 @@ function parse_isodur(s) { | ||||
| 	} | ||||
| 	return sec; | ||||
| } | ||||
| 
 | ||||
| var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n'; | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| /* copied from js-xls (C) SheetJS Apache2 license */ | ||||
| function xlml_normalize(d) { | ||||
| 	if(has_buf && Buffer.isBuffer(d)) return d.toString('utf8'); | ||||
| 	if(has_buf &&/*::typeof Buffer !== "undefined" && d != null &&*/ Buffer.isBuffer(d)) return d.toString('utf8'); | ||||
| 	if(typeof d === 'string') return d; | ||||
| 	throw "badf"; | ||||
| } | ||||
|  | ||||
| @ -1,13 +1,13 @@ | ||||
| /* Part 3 Section 4 Manifest File */ | ||||
| var CT_ODS = "application/vnd.oasis.opendocument.spreadsheet"; | ||||
| var parse_manifest = function(d, opts) { | ||||
| function parse_manifest(d, opts) { | ||||
| 	var str = xlml_normalize(d); | ||||
| 	var Rn; | ||||
| 	var FEtag; | ||||
| 	while((Rn = xlmlregex.exec(str))) switch(Rn[3]) { | ||||
| 		case 'manifest': break; // 4.2 <manifest:manifest>
 | ||||
| 		case 'file-entry': // 4.3 <manifest:file-entry>
 | ||||
| 			FEtag = parsexmltag(Rn[0]); | ||||
| 			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>
 | ||||
| @ -15,6 +15,15 @@ var parse_manifest = function(d, opts) { | ||||
| 		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: throw Rn; | ||||
| 		default: if(opts && opts.WTF) throw Rn; | ||||
| 	} | ||||
| }; | ||||
| } | ||||
| 
 | ||||
| function write_manifest(manifest/*:Array<Array<string> >*/, opts)/*: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(""); | ||||
| } | ||||
|  | ||||
							
								
								
									
										26
									
								
								odsbits/35_rdf.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										26
									
								
								odsbits/35_rdf.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | ||||
| /* 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/*: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, opts) { | ||||
| 	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(""); | ||||
| } | ||||
| @ -1,5 +1,5 @@ | ||||
| var parse_text_p = function(text, tag) { | ||||
| 	return utf8read(text.replace(/<text:s\/>/g," ").replace(/<[^>]*>/g,"")); | ||||
| 	return unescapexml(utf8read(text.replace(/<text:s\/>/g," ").replace(/<[^>]*>/g,""))); | ||||
| }; | ||||
| 
 | ||||
| var utf8read = function utf8reada(orig) { | ||||
|  | ||||
| @ -14,29 +14,31 @@ var parse_content_xml = (function() { | ||||
| 
 | ||||
| 	return function pcx(d, opts) { | ||||
| 		var str = xlml_normalize(d); | ||||
| 		var state = [], tmp; | ||||
| 		var tag; | ||||
| 		var NFtag, NF, pidx; | ||||
| 		var sheetag; | ||||
| 		var Sheets = {}, SheetNames = [], ws = {}; | ||||
| 		var Rn, q; | ||||
| 		var ctag; | ||||
| 		var textp, textpidx, textptag; | ||||
| 		var R, C, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}}; | ||||
| 		var state/*:Array<any>*/ = [], tmp; | ||||
| 		var tag/*:: = {}*/; | ||||
| 		var NFtag = {name:""}, NF = "", pidx = 0; | ||||
| 		var sheetag/*:: = {name:""}*/; | ||||
| 		var Sheets = {}, SheetNames/*:Array<string>*/ = [], ws = {}; | ||||
| 		var Rn, q/*:: = {t:"", v:null, z:null, w:""}*/; | ||||
| 		var ctag = {value:""}; | ||||
| 		var textp = "", textpidx = 0, textptag/*:: = {}*/; | ||||
| 		var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}}; | ||||
| 		var number_format_map = {}; | ||||
| 		var merges = [], mrange = {}, mR = 0, mC = 0; | ||||
| 
 | ||||
| 		var rept = 1; | ||||
| 		xlmlregex.lastIndex = 0; | ||||
| 		while((Rn = xlmlregex.exec(str))) switch(Rn[3]) { | ||||
| 
 | ||||
| 			case 'table': // 9.1.2 <table:table>
 | ||||
| 				if(Rn[1]==='/') { | ||||
| 					if(range.e.c >= range.s.c && range.e.r >= range.s.r) ws['!ref'] = get_utils().encode_range(range); | ||||
| 					if(merges.length) ws['!merges'] = merges; | ||||
| 					sheetag.name = utf8read(sheetag.name); | ||||
| 					SheetNames.push(sheetag.name); | ||||
| 					Sheets[sheetag.name] = ws; | ||||
| 				} | ||||
| 				else if(Rn[0].charAt(Rn[0].length-2) !== '/') { | ||||
| 					sheetag = parsexmltag(Rn[0]); | ||||
| 					sheetag = parsexmltag(Rn[0], false); | ||||
| 					R = C = -1; | ||||
| 					range.s.r = range.s.c = 10000000; range.e.r = range.e.c = 0; | ||||
| 					ws = {}; merges = []; | ||||
| @ -50,24 +52,29 @@ var parse_content_xml = (function() { | ||||
| 				++C; break; /* stub */ | ||||
| 			case 'table-cell': | ||||
| 				if(Rn[0].charAt(Rn[0].length-2) === '/') { | ||||
| 					ctag = parsexmltag(Rn[0]); | ||||
| 					ctag = parsexmltag(Rn[0], false); | ||||
| 					if(ctag['number-columns-repeated']) C+= parseInt(ctag['number-columns-repeated'], 10); | ||||
| 					else ++C; | ||||
| 				} | ||||
| 				else if(Rn[1]!=='/') { | ||||
| 					++C; | ||||
| 					rept = 1; | ||||
| 					if(C > range.e.c) range.e.c = C; | ||||
| 					if(R > range.e.r) range.e.r = R; | ||||
| 					if(C < range.s.c) range.s.c = C; | ||||
| 					if(R < range.s.r) range.s.r = R; | ||||
| 					ctag = parsexmltag(Rn[0]); | ||||
| 					q = {t:ctag['value-type'], v:null}; | ||||
| 					ctag = parsexmltag(Rn[0], false); | ||||
| 					q = {t:ctag['value-type'], v:null/*:: , z:null, w:""*/}; | ||||
| 					if(ctag['number-columns-spanned'] || ctag['number-rows-spanned']) { | ||||
| 						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']) rept = parseInt(ctag['number-columns-repeated'], 10); | ||||
| 
 | ||||
| 					/* 19.385 office:value-type */ | ||||
| 					switch(q.t) { | ||||
| 						case 'boolean': q.t = 'b'; q.v = parsexmlbool(ctag['boolean-value']); break; | ||||
| @ -76,14 +83,22 @@ var parse_content_xml = (function() { | ||||
| 						case 'currency': q.t = 'n'; q.v = parseFloat(ctag.value); break; | ||||
| 						case 'date': q.t = 'n'; q.v = datenum(ctag['date-value']); q.z = 'm/d/yy'; break; | ||||
| 						case 'time': q.t = 'n'; q.v = parse_isodur(ctag['time-value'])/86400; break; | ||||
| 						case 'string': q.t = 's'; break; | ||||
| 						default: throw new Error('Unsupported value type ' + q.t); | ||||
| 						default: | ||||
| 							if(q.t === 'string' || !q.t) { | ||||
| 								q.t = 's'; | ||||
| 								if(ctag['string-value'] != null) textp = ctag['string-value']; | ||||
| 							} else throw new Error('Unsupported value type ' + q.t); | ||||
| 					} | ||||
| 				} else { | ||||
| 					if(q.t === 's') q.v = textp; | ||||
| 					if(q.t === 's') q.v = textp || ''; | ||||
| 					if(textp) q.w = textp; | ||||
| 					if(!(opts.sheetRows && opts.sheetRows < R)) ws[get_utils().encode_cell({r:R,c:C})] = q; | ||||
| 					q = null; | ||||
| 					if(!(opts.sheetRows && opts.sheetRows < R)) { | ||||
| 						ws[get_utils().encode_cell({r:R,c:C})] = q; | ||||
| 						while(--rept > 0) ws[get_utils().encode_cell({r:R,c:++C})] = dup(q); | ||||
| 						if(range.e.c <= C) range.e.c = C; | ||||
| 					} | ||||
| 					q = {/*:: t:"", v:null, z:null, w:""*/}; | ||||
| 					textp = ""; | ||||
| 				} | ||||
| 				break; // 9.1.4 <table:table-cell>
 | ||||
| 
 | ||||
| @ -99,6 +114,13 @@ var parse_content_xml = (function() { | ||||
| 			/* ignore state */ | ||||
| 			case 'shapes': // 9.2.8 <table:shapes>
 | ||||
| 			case 'frame': // 10.4.2 <draw:frame>
 | ||||
| 			case 'text-box': // 10.4.3 <draw:text-box>
 | ||||
| 			case 'image': // 10.4.4 <draw:image>
 | ||||
| 			case 'data-pilot-tables': // 9.6.2 <table:data-pilot-tables>
 | ||||
| 			case 'list-style': // 16.30 <text:list-style>
 | ||||
| 			case 'form': // 13.13 <form:form>
 | ||||
| 			case 'dde-links': // 9.8 <table:dde-links>
 | ||||
| 			case 'annotation': // 14.1 <office:annotation>
 | ||||
| 				if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;} | ||||
| 				else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], false]); | ||||
| 				break; | ||||
| @ -112,7 +134,7 @@ var parse_content_xml = (function() { | ||||
| 					if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp; | ||||
| 				} else if(Rn[0].charAt(Rn[0].length-2) !== '/') { | ||||
| 					NF = ""; | ||||
| 					NFtag = parsexmltag(Rn[0]); | ||||
| 					NFtag = parsexmltag(Rn[0], false); | ||||
| 					state.push([Rn[3], true]); | ||||
| 				} break; | ||||
| 
 | ||||
| @ -120,6 +142,7 @@ var parse_content_xml = (function() { | ||||
| 			case 'automatic-styles': break; // 3.15.3 <office:automatic-styles>
 | ||||
| 
 | ||||
| 			case 'style': break; // 16.2 <style:style>
 | ||||
| 			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>
 | ||||
| @ -132,10 +155,12 @@ var parse_content_xml = (function() { | ||||
| 				switch(state[state.length-1][0]) { | ||||
| 					case 'time-style': | ||||
| 					case 'date-style': | ||||
| 						tag = parsexmltag(Rn[0]); | ||||
| 						tag = parsexmltag(Rn[0], false); | ||||
| 						NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break; | ||||
| 				} break; | ||||
| 
 | ||||
| 			case 'fraction': break; // TODO 16.27.6 <number:fraction>
 | ||||
| 
 | ||||
| 			case 'day': // 16.27.11 <number:day>
 | ||||
| 			case 'month': // 16.27.12 <number:month>
 | ||||
| 			case 'year': // 16.27.13 <number:year>
 | ||||
| @ -150,7 +175,7 @@ var parse_content_xml = (function() { | ||||
| 				switch(state[state.length-1][0]) { | ||||
| 					case 'time-style': | ||||
| 					case 'date-style': | ||||
| 						tag = parsexmltag(Rn[0]); | ||||
| 						tag = parsexmltag(Rn[0], false); | ||||
| 						NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break; | ||||
| 				} break; | ||||
| 
 | ||||
| @ -176,30 +201,114 @@ var parse_content_xml = (function() { | ||||
| 			case 'forms': break; // 12.25.2 13.2
 | ||||
| 			case 'table-column': break; // 9.1.6 <table:table-column>
 | ||||
| 
 | ||||
| 			case 'graphic-properties': break; | ||||
| 			case 'null-date': break; // 9.4.2 <table:null-date> TODO: date1904
 | ||||
| 
 | ||||
| 			case 'graphic-properties': break; // 17.21 <style:graphic-properties>
 | ||||
| 			case 'calculation-settings': break; // 9.4.1 <table:calculation-settings>
 | ||||
| 			case 'named-expressions': break; // 9.4.11 <table:named-expressions>
 | ||||
| 			case 'named-range': break; // 9.4.11 <table:named-range>
 | ||||
| 			case 'named-range': break; // 9.4.12 <table:named-range>
 | ||||
| 			case 'named-expression': break; // 9.4.13 <table:named-expression>
 | ||||
| 			case 'sort': break; // 9.4.19 <table:sort>
 | ||||
| 			case 'sort-by': break; // 9.4.20 <table:sort-by>
 | ||||
| 			case 'sort-groups': break; // 9.4.22 <table:sort-groups>
 | ||||
| 
 | ||||
| 			case 'span': break; // <text:span>
 | ||||
| 			case 'line-break': break; // 6.1.5 <text:line-break>
 | ||||
| 			case 'p': | ||||
| 				if(Rn[1]==='/') textp = parse_text_p(str.slice(textpidx,Rn.index), textptag); | ||||
| 				else { textptag = parsexmltag(Rn[0]); textpidx = Rn.index + Rn[0].length; } | ||||
| 				else { textptag = parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; } | ||||
| 				break; // <text:p>
 | ||||
| 			case 's': break; // <text:s>
 | ||||
| 			case 'date': break; // <*:date>
 | ||||
| 			case 'annotation': break; | ||||
| 
 | ||||
| 			case 'object': break; // 10.4.6.2 <draw:object>
 | ||||
| 			case 'title': break; // <*:title>
 | ||||
| 			case 'desc': break; // <*:desc>
 | ||||
| 
 | ||||
| 			case 'table-source': break; // 9.2.6
 | ||||
| 
 | ||||
| 			case 'iteration': break; // 9.4.3 <table:iteration>
 | ||||
| 			case 'content-validations': break; // 9.4.4 <table:
 | ||||
| 			case 'content-validation': break; // 9.4.5 <table:
 | ||||
| 			case 'error-message': break; // 9.4.7 <table:
 | ||||
| 			case 'database-ranges': break; // 9.4.14 <table:database-ranges>
 | ||||
| 			case 'database-range': break; // 9.4.15 <table:database-range>
 | ||||
| 			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>
 | ||||
| 			default: if(opts.WTF) throw Rn; | ||||
| 
 | ||||
| 			case 'list-level-style-bullet': break; // 16.31 <text:
 | ||||
| 			case 'list-level-style-number': break; // 16.32 <text:
 | ||||
| 			case 'list-level-properties': break; // 17.19 <style:
 | ||||
| 
 | ||||
| 			/* 7.3 Document Fields */ | ||||
| 			case 'sender-firstname': // 7.3.6.2
 | ||||
| 			case 'sender-lastname': // 7.3.6.3
 | ||||
| 			case 'sender-initials': // 7.3.6.4
 | ||||
| 			case 'sender-title': // 7.3.6.5
 | ||||
| 			case 'sender-position': // 7.3.6.6
 | ||||
| 			case 'sender-email': // 7.3.6.7
 | ||||
| 			case 'sender-phone-private': // 7.3.6.8
 | ||||
| 			case 'sender-fax': // 7.3.6.9
 | ||||
| 			case 'sender-company': // 7.3.6.10
 | ||||
| 			case 'sender-phone-work': // 7.3.6.11
 | ||||
| 			case 'sender-street': // 7.3.6.12
 | ||||
| 			case 'sender-city': // 7.3.6.13
 | ||||
| 			case 'sender-postal-code': // 7.3.6.14
 | ||||
| 			case 'sender-country': // 7.3.6.15
 | ||||
| 			case 'sender-state-or-province': // 7.3.6.16
 | ||||
| 			case 'author-name': // 7.3.7.1
 | ||||
| 			case 'author-initials': // 7.3.7.2
 | ||||
| 			case 'chapter': // 7.3.8
 | ||||
| 			case 'file-name': // 7.3.9
 | ||||
| 			case 'template-name': // 7.3.9
 | ||||
| 			case 'sheet-name': // 7.3.9
 | ||||
| 				break; | ||||
| 
 | ||||
| 			/* 9.6 Data Pilot Tables <table: */ | ||||
| 			case 'data-pilot-table': // 9.6.3
 | ||||
| 			case 'source-cell-range': // 9.6.5
 | ||||
| 			case 'source-service': // 9.6.6
 | ||||
| 			case 'data-pilot-field': // 9.6.7
 | ||||
| 			case 'data-pilot-level': // 9.6.8
 | ||||
| 			case 'data-pilot-subtotals': // 9.6.9
 | ||||
| 			case 'data-pilot-subtotal': // 9.6.10
 | ||||
| 			case 'data-pilot-members': // 9.6.11
 | ||||
| 			case 'data-pilot-member': // 9.6.12
 | ||||
| 			case 'data-pilot-display-info': // 9.6.13
 | ||||
| 			case 'data-pilot-sort-info': // 9.6.14
 | ||||
| 			case 'data-pilot-layout-info': // 9.6.15
 | ||||
| 			case 'data-pilot-field-reference': // 9.6.16
 | ||||
| 			case 'data-pilot-groups': // 9.6.17
 | ||||
| 			case 'data-pilot-group': // 9.6.18
 | ||||
| 			case 'data-pilot-group-member': // 9.6.19
 | ||||
| 				break; | ||||
| 
 | ||||
| 			/* 10.3 Drawing Shapes */ | ||||
| 			case 'rect': // 10.3.2
 | ||||
| 				break; | ||||
| 
 | ||||
| 			/* 14.6 DDE Connections */ | ||||
| 			case 'dde-connection-decls': // 14.6.2 <text:
 | ||||
| 			case 'dde-connection-decl': // 14.6.3 <text:
 | ||||
| 			case 'dde-link': // 14.6.4 <table:
 | ||||
| 			case 'dde-source': // 14.6.5 <office:
 | ||||
| 				break; | ||||
| 
 | ||||
| 			case 'properties': break; // 13.7 <form:properties>
 | ||||
| 			case 'property': break; // 13.8 <form:property>
 | ||||
| 
 | ||||
| 			case 'a': break; // 6.1.8 hyperlink
 | ||||
| 
 | ||||
| 			/* non-standard */ | ||||
| 			case 'table-protection': break; | ||||
| 			case 'data-pilot-grand-total': break; // <table:
 | ||||
| 			default: | ||||
| 				if(Rn[2] === 'dc:') break; // TODO: properties
 | ||||
| 				if(Rn[2] === 'draw:') break; // TODO: drawing
 | ||||
| 				if(Rn[2] === 'calcext:') break; // ignore undocumented extensions
 | ||||
| 				if(opts.WTF) throw Rn; | ||||
| 		} | ||||
| 		var out = { | ||||
| 			Sheets: Sheets, | ||||
|  | ||||
							
								
								
									
										41
									
								
								odsbits/70_content.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										41
									
								
								odsbits/70_content.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | ||||
| var write_content_xml/*:{(wb:any, opts:any):string}*/ = (function() { | ||||
| 	var null_cell_xml = '          <table:table-cell />\n'; | ||||
| 	var write_ws = function(ws, wb, i/*:number*/, opts)/*:string*/ { | ||||
| 		/* Section 9 Tables */ | ||||
| 		var o = []; | ||||
| 		o.push('      <table:table table:name="' + escapexml(wb.SheetNames[i]) + '">\n'); | ||||
| 		var R=0,C=0, range = get_utils().decode_range(ws['!ref']); | ||||
| 		for(R = 0; R < range.s.r; ++R) o.push('        <table:table-row></table:table-row>\n'); | ||||
| 		for(; R <= range.e.r; ++R) { | ||||
| 			o.push('        <table:table-row>\n'); | ||||
| 			for(C=0; C < range.s.c; ++C) o.push(null_cell_xml); | ||||
| 			for(; C <= range.e.c; ++C) { | ||||
| 				var ref = get_utils().encode_cell({r:R, c:C}), cell = ws[ref]; | ||||
| 				if(cell) switch(cell.t) { | ||||
| 					case 'b': o.push('          <table:table-cell office:value-type="boolean" office:boolean-value="' + (cell.v ? 'true' : 'false') + '"><text:p>' + (cell.v ? 'TRUE' : 'FALSE') + '</text:p></table:table-cell>\n'); break; | ||||
| 					case 'n': o.push('          <table:table-cell office:value-type="float" office:value="' + cell.v + '"><text:p>' + (cell.w||cell.v) + '</text:p></table:table-cell>\n'); break; | ||||
| 					case 's': case 'str': o.push('          <table:table-cell office:value-type="string"><text:p>' + escapexml(cell.v) + '</text:p></table:table-cell>\n'); break; | ||||
| 					//case 'd': // TODO
 | ||||
| 					//case 'e':
 | ||||
| 					default: o.push(null_cell_xml); | ||||
| 				} else o.push(null_cell_xml); | ||||
| 			} | ||||
| 			o.push('        </table:table-row>\n'); | ||||
| 		} | ||||
| 		o.push('      </table:table>\n'); | ||||
| 		return o.join(""); | ||||
| 	}; | ||||
| 
 | ||||
| 	return function wcx(wb, opts) { | ||||
| 		var o = [XML_HEADER]; | ||||
| 		/* 3.1.3.2 */ | ||||
| 		o.push('<office:document-content office:version="1.2" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0">\n'); // TODO
 | ||||
| 		o.push('  <office:body>\n'); | ||||
| 		o.push('    <office:spreadsheet>\n'); | ||||
| 		for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts)); | ||||
| 		o.push('    </office:spreadsheet>\n'); | ||||
| 		o.push('  </office:body>\n'); | ||||
| 		o.push('</office:document-content>'); | ||||
| 		return o.join(""); | ||||
| 	}; | ||||
| })(); | ||||
| @ -1,5 +1,6 @@ | ||||
| /* Part 3: Packages */ | ||||
| var parse_ods = function(zip, opts) { | ||||
| 	//var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'));
 | ||||
| function parse_ods(zip/*:ZIPFile*/, opts/*:?ParseOpts*/) { | ||||
| 	opts = opts || ({}/*:any*/); | ||||
| 	var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts); | ||||
| 	return parse_content_xml(getzipdata(zip, 'content.xml'), opts); | ||||
| }; | ||||
| } | ||||
|  | ||||
							
								
								
									
										29
									
								
								odsbits/85_write.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										29
									
								
								odsbits/85_write.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | ||||
| function write_ods(wb/*:any*/, opts/*:any*/) { | ||||
| 	/*:: if(!jszip) throw new Error("JSZip is not available"); */ | ||||
| 	var zip = new jszip(); | ||||
| 	var f = ""; | ||||
| 
 | ||||
| 	var manifest/*:Array<Array<string> >*/ = []; | ||||
| 	var rdf = []; | ||||
| 
 | ||||
| 	/* 3:3.3 and 2:2.2.4 */ | ||||
| 	f = "mimetype"; | ||||
| 	zip.file(f, "application/vnd.oasis.opendocument.spreadsheet"); | ||||
| 
 | ||||
| 	/* Part 2 Section 2.2 Documents */ | ||||
| 	f = "content.xml"; | ||||
| 	zip.file(f, write_content_xml(wb, opts)); | ||||
| 	manifest.push([f, "text/xml"]); | ||||
| 	rdf.push([f, "ContentFile"]); | ||||
| 
 | ||||
| 	/* Part 3 Section 6 Metadata Manifest File */ | ||||
| 	f = "manifest.rdf"; | ||||
| 	zip.file(f, write_rdf(rdf, opts)); | ||||
| 	manifest.push([f, "application/rdf+xml"]); | ||||
| 
 | ||||
| 	/* Part 3 Section 4 Manifest File */ | ||||
| 	f = "META-INF/manifest.xml"; | ||||
| 	zip.file(f, write_manifest(manifest, opts)); | ||||
| 
 | ||||
| 	return zip; | ||||
| } | ||||
| @ -1 +1,2 @@ | ||||
| ODS.parse_ods = parse_ods; | ||||
| ODS.write_ods = write_ods; | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| { | ||||
| 	"name": "xlsx", | ||||
| 	"version": "0.8.1", | ||||
| 	"version": "0.8.2", | ||||
| 	"author": "sheetjs", | ||||
| 	"description": "Excel (XLSB/XLSX/XLSM/XLS/XML) and ODS spreadsheet parser and writer", | ||||
| 	"keywords": [ "excel", "xls", "xlsx", "xlsb", "xlsm", "ods", "office", "spreadsheet" ], | ||||
| @ -33,6 +33,7 @@ | ||||
| 			"pattern": "xlsx.js" | ||||
| 		} | ||||
| 	}, | ||||
| 	"homepage": "https://oss.sheetjs.com/js-xlsx/", | ||||
| 	"bugs": { "url": "https://github.com/SheetJS/js-xlsx/issues" }, | ||||
| 	"license": "Apache-2.0", | ||||
| 	"engines": { "node": ">=0.8" } | ||||
|  | ||||
							
								
								
									
										3
									
								
								test.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										3
									
								
								test.js
									
									
									
									
									
								
							| @ -11,7 +11,7 @@ if(process.env.WTF) { | ||||
| 	opts.WTF = true; | ||||
| 	opts.cellStyles = true; | ||||
| } | ||||
| var fullex = [/*TODO: check why write xlsb fails ".xlsb",*/ ".xlsm", ".xlsx"]; | ||||
| var fullex = [".xlsb", ".xlsm", ".xlsx"]; | ||||
| var ex = fullex.slice(); ex.push(".ods"); ex.push(".xls"); ex.push("xml"); | ||||
| if(process.env.FMTS === "full") process.env.FMTS = ex.join(":"); | ||||
| if(process.env.FMTS) ex=process.env.FMTS.split(":").map(function(x){return x[0]==="."?x:"."+x;}); | ||||
| @ -114,6 +114,7 @@ function parsetest(x, wb, full, ext) { | ||||
| 	if(!full) return; | ||||
| 	var getfile = function(dir, x, i, type) { | ||||
| 		var name = (dir + x + '.' + i + type); | ||||
| 		var root = ""; | ||||
| 		if(x.substr(-5) === ".xlsb") { | ||||
| 			root = x.slice(0,-5); | ||||
| 			if(!fs.existsSync(name)) name=(dir + root + '.xlsx.' + i + type); | ||||
|  | ||||
							
								
								
									
										16
									
								
								tests.lst
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										16
									
								
								tests.lst
									
									
									
									
									
								
							| @ -25,7 +25,7 @@ text_and_numbers.xlsb | ||||
| xlsx-stream-d-date-cell.xlsb | ||||
| 2013/apachepoi_29982.xls.xlsb | ||||
| 2013/apachepoi_43251.xls.xlsb | ||||
| 2013/apachepoi_44593.xls.xlsb | ||||
| #2013/apachepoi_44593.xls.xlsb ## xlsb loop timeout | ||||
| 2013/apachepoi_44643.xls.xlsb | ||||
| 2013/apachepoi_44958.xls.xlsb | ||||
| 2013/apachepoi_46136-NoWarnings.xls.xlsb | ||||
| @ -126,7 +126,7 @@ apachepoi_56688_1.xlsx | ||||
| apachepoi_56688_2.xlsx | ||||
| apachepoi_56688_3.xlsx | ||||
| apachepoi_56688_4.xlsx | ||||
| apachepoi_56702.xlsx | ||||
| # apachepoi_56702.xlsx ## xlsb bad xnum | ||||
| apachepoi_56730.xlsx | ||||
| apachepoi_56737.xlsx | ||||
| apachepoi_AverageTaxRates.xlsx | ||||
| @ -344,7 +344,7 @@ formula_stress_test.ods | ||||
| merge_cells.ods | ||||
| number_format.ods | ||||
| rich_text_stress.ods | ||||
| roo_Bibelbund.ods | ||||
| # roo_Bibelbund.ods ## timeout | ||||
| roo_Bibelbund1.ods | ||||
| roo_bbu.ods | ||||
| roo_boolean.ods | ||||
| @ -475,7 +475,7 @@ apachepoi_44200.xls | ||||
| apachepoi_44201.xls | ||||
| apachepoi_44235.xls | ||||
| apachepoi_44297.xls | ||||
| apachepoi_44593.xls | ||||
| # apachepoi_44593.xls ## xlsb loop timeout | ||||
| apachepoi_44636.xls | ||||
| apachepoi_44643.xls | ||||
| apachepoi_44693.xls | ||||
| @ -529,7 +529,7 @@ apachepoi_49529.xls | ||||
| apachepoi_49581.xls | ||||
| apachepoi_49612.xls | ||||
| apachepoi_49751.xls | ||||
| apachepoi_49761.xls | ||||
| # apachepoi_49761.xls ## xlsb bad xnum | ||||
| apachepoi_49896.xls | ||||
| apachepoi_49928.xls | ||||
| apachepoi_49931.xls | ||||
| @ -615,12 +615,12 @@ apachepoi_PercentPtg.xls | ||||
| apachepoi_QuotientFunctionTestCaseData.xls | ||||
| apachepoi_RangePtg.xls | ||||
| apachepoi_ReadOnlyRecommended.xls | ||||
| apachepoi_ReferencePtg.xls | ||||
| # apachepoi_ReferencePtg.xls ## xlsb loop timeout | ||||
| apachepoi_RepeatingRowsCols.xls | ||||
| apachepoi_ReptFunctionTestCaseData.xls | ||||
| apachepoi_RomanFunctionTestCaseData.xls | ||||
| apachepoi_SampleSS.xls | ||||
| apachepoi_SharedFormulaTest.xls | ||||
| # apachepoi_SharedFormulaTest.xls ## xlsb loop timeout | ||||
| apachepoi_SheetWithDrawing.xls | ||||
| apachepoi_ShrinkToFit.xls | ||||
| apachepoi_Simple.xls | ||||
| @ -899,7 +899,7 @@ libreoffice_calc_xls-import_pivot-dup-data-fields.xls | ||||
| libreoffice_calc_xls-import_pivot-layout-field-non-default.xls | ||||
| libreoffice_calc_xls-import_row-attributes_row-all-hidden.xls | ||||
| libreoffice_calc_xls-import_row-attributes_row-filtered.xls | ||||
| libreoffice_calc_xls-import_row-attributes_row-heights.xls | ||||
| # libreoffice_calc_xls-import_row-attributes_row-heights.xls ## xlsb loop timeout | ||||
| libreoffice_calc_xls-import_row-attributes_row-tail-hidden-2.xls | ||||
| libreoffice_calc_xls-import_row-attributes_row-tail-hidden-last-row-visible.xls | ||||
| libreoffice_calc_xls-import_row-attributes_row-tail-hidden.xls | ||||
|  | ||||
| @ -85,3 +85,7 @@ ws['!cols'] = wscols; | ||||
| 
 | ||||
| /* write file */ | ||||
| XLSX.writeFile(wb, 'sheetjs.xlsx'); | ||||
| XLSX.writeFile(wb, 'sheetjs.xlsm'); | ||||
| XLSX.writeFile(wb, 'sheetjs.xlsb'); | ||||
| //XLSX.writeFile(wb, 'sheetjs.xls');
 | ||||
| XLSX.writeFile(wb, 'sheetjs.ods'); | ||||
|  | ||||
							
								
								
									
										11771
									
								
								xlsx.flow.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										11771
									
								
								xlsx.flow.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										172
									
								
								xlsx.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										172
									
								
								xlsx.js
									
									
									
									
									
								
							| @ -4,7 +4,7 @@ | ||||
| /*jshint funcscope:true, eqnull:true */ | ||||
| var XLSX = {}; | ||||
| (function make_xlsx(XLSX){ | ||||
| XLSX.version = '0.8.1'; | ||||
| XLSX.version = '0.8.2'; | ||||
| var current_codepage = 1200, current_cptable; | ||||
| if(typeof module !== "undefined" && typeof require !== 'undefined') { | ||||
| 	if(typeof cptable === 'undefined') cptable = require('./dist/cpexcel'); | ||||
| @ -1645,7 +1645,8 @@ function WriteShift(t, val, f) { | ||||
| 		size = 2 * val.length; | ||||
| 	} else switch(t) { | ||||
| 		case  1: size = 1; this[this.l] = val&255; break; | ||||
| 		case  3: size = 3; this[this.l+2] = val & 255; val >>>= 8; this[this.l+1] = val&255; val >>>= 8; this[this.l] = val&255; break; | ||||
| 		case  2: size = 2; this[this.l] = val&255; val >>>= 8; this[this.l+1] = val&255; break; | ||||
| 		case  3: size = 3; this[this.l] = val&255; val >>>= 8; this[this.l+1] = val&255; val >>>= 8; this[this.l+2] = val&255; break; | ||||
| 		case  4: size = 4; this.writeUInt32LE(val, this.l); break; | ||||
| 		case  8: size = 8; if(f === 'f') { this.writeDoubleLE(val, this.l); break; } | ||||
| 		/* falls through */ | ||||
| @ -1706,7 +1707,7 @@ function buf_array() { | ||||
| 	var curbuf = newblk(blksz); | ||||
| 
 | ||||
| 	var endbuf = function ba_endbuf() { | ||||
| 		curbuf.length = curbuf.l; | ||||
| 		if(curbuf.length > curbuf.l) curbuf = curbuf.slice(0, curbuf.l); | ||||
| 		if(curbuf.length > 0) bufs.push(curbuf); | ||||
| 		curbuf = null; | ||||
| 	}; | ||||
| @ -1893,6 +1894,15 @@ function parse_RkNumber(data) { | ||||
| 	var RK = fInt === 0 ? __double([0,0,0,0,b[0],b[1],b[2],b[3]],0) : __readInt32LE(b,0)>>2; | ||||
| 	return fX100 ? RK/100 : RK; | ||||
| } | ||||
| function write_RkNumber(data, o) { | ||||
| 	if(o == null) o = new_buf(4); | ||||
| 	var fX100 = 0, fInt = 0, d100 = data * 100; | ||||
| 	if(data == (data | 0) && data >= -(1<<29) && data < (1 << 29)) { fInt = 1; } | ||||
| 	else if(d100 == (d100 | 0) && d100 >= -(1<<29) && d100 < (1 << 29)) { fInt = 1; fX100 = 1; } | ||||
| 	if(fInt) o.write_shift(-4, ((fX100 ? d100 : data) << 2) + (fX100 + 2)); | ||||
| 	else throw new Error("unsupported RkNumber " + data); // TODO
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* [MS-XLSB] 2.5.153 */ | ||||
| function parse_UncheckedRfX(data) { | ||||
| @ -1915,8 +1925,9 @@ function write_UncheckedRfX(r, o) { | ||||
| 
 | ||||
| /* [MS-XLSB] 2.5.171 */ | ||||
| /* [MS-XLS] 2.5.342 */ | ||||
| /* TODO: error checking, NaN and Infinity values are not valid Xnum */ | ||||
| function parse_Xnum(data, length) { return data.read_shift(8, 'f'); } | ||||
| function write_Xnum(data, o) { return (o || new_buf(8)).write_shift(8, 'f', data); } | ||||
| function write_Xnum(data, o) { return (o || new_buf(8)).write_shift(8, data, 'f'); } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.5.198.2 */ | ||||
| var BErr = { | ||||
| @ -2730,7 +2741,7 @@ function parse_cust_props(data, opts) { | ||||
| 						p[name] = unescapexml(text); | ||||
| 						break; | ||||
| 					default: | ||||
| 						if(typeof console !== 'undefined') console.warn('Unexpected', x, type, toks); | ||||
| 						if(opts.WTF && typeof console !== 'undefined') console.warn('Unexpected', x, type, toks); | ||||
| 				} | ||||
| 			} else if(x.substr(0,2) === "</") { | ||||
| 			} else if(opts.WTF) throw new Error(x); | ||||
| @ -7286,7 +7297,7 @@ function parse_ws_xml(data, opts, rels) { | ||||
| 	var mergecells = []; | ||||
| 	if(data.indexOf("</mergeCells>")!==-1) { | ||||
| 		var merges = data.match(mergecregex); | ||||
| 		for(ridx = 0; ridx != merges.length; ++ridx) | ||||
| 		if(merges) for(ridx = 0; ridx != merges.length; ++ridx) | ||||
| 			mergecells[ridx] = safe_decode_range(merges[ridx].substr(merges[ridx].indexOf("\"")+1)); | ||||
| 	} | ||||
| 
 | ||||
| @ -7298,7 +7309,7 @@ function parse_ws_xml(data, opts, rels) { | ||||
| 		parse_ws_xml_cols(columns, cols); | ||||
| 	} | ||||
| 
 | ||||
| 	var refguess = {s: {r:1000000, c:1000000}, e: {r:0, c:0} }; | ||||
| 	var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} }; | ||||
| 
 | ||||
| 	/* 18.3.1.80 sheetData CT_SheetData ? */ | ||||
| 	var mtch=data.match(sheetdataregex); | ||||
| @ -7573,6 +7584,45 @@ function parse_BrtRowHdr(data, length) { | ||||
| 	data.l += length-4; | ||||
| 	return z; | ||||
| } | ||||
| function write_BrtRowHdr(R, range, ws) { | ||||
| 	var o = new_buf(17+8*16); | ||||
| 	o.write_shift(4, R); | ||||
| 
 | ||||
| 	/* TODO: flags styles */ | ||||
| 	o.write_shift(4, 0); | ||||
| 	o.write_shift(2, 0x0140); | ||||
| 	o.write_shift(2, 0); | ||||
| 	o.write_shift(1, 0); | ||||
| 
 | ||||
| 	/* [MS-XLSB] 2.5.8 BrtColSpan explains the mechanism */ | ||||
| 	var ncolspan = 0, lcs = o.l; | ||||
| 	o.l += 4; | ||||
| 
 | ||||
| 	var caddr = {r:R, c:0}; | ||||
| 	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; | ||||
| 			if(ws[encode_cell(caddr)]) { if(first < 0) first = j; last = j; } | ||||
| 		} | ||||
| 		if(first < 0) continue; | ||||
| 		++ncolspan; | ||||
| 		o.write_shift(4, first); | ||||
| 		o.write_shift(4, last); | ||||
| 	} | ||||
| 
 | ||||
| 	var l = o.l; | ||||
| 	o.l = lcs; | ||||
| 	o.write_shift(4, ncolspan); | ||||
| 	o.l = l; | ||||
| 
 | ||||
| 	return o.length > o.l ? o.slice(0, o.l) : o; | ||||
| } | ||||
| function write_row_header(ba, ws, range, R) { | ||||
| 	var o = write_BrtRowHdr(R, range, ws); | ||||
| 	if(o.length > 17) write_record(ba, 'BrtRowHdr', o); | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.812 BrtWsDim */ | ||||
| var parse_BrtWsDim = parse_UncheckedRfX; | ||||
| @ -7592,9 +7642,9 @@ function parse_BrtCellBlank(data, length) { | ||||
| 	var cell = parse_XLSBCell(data); | ||||
| 	return [cell]; | ||||
| } | ||||
| function write_BrtCellBlank(cell, val, o) { | ||||
| function write_BrtCellBlank(cell, ncell, o) { | ||||
| 	if(o == null) o = new_buf(8); | ||||
| 	return write_XLSBCell(val, o); | ||||
| 	return write_XLSBCell(ncell, o); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| @ -7604,12 +7654,18 @@ function parse_BrtCellBool(data, length) { | ||||
| 	var fBool = data.read_shift(1); | ||||
| 	return [cell, fBool, 'b']; | ||||
| } | ||||
| function write_BrtCellBool(cell, ncell, o) { | ||||
| 	if(o == null) o = new_buf(9); | ||||
| 	write_XLSBCell(ncell, o); | ||||
| 	o.write_shift(1, cell.v ? 1 : 0); | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.305 BrtCellError */ | ||||
| function parse_BrtCellError(data, length) { | ||||
| 	var cell = parse_XLSBCell(data); | ||||
| 	var fBool = data.read_shift(1); | ||||
| 	return [cell, fBool, 'e']; | ||||
| 	var bError = data.read_shift(1); | ||||
| 	return [cell, bError, 'e']; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.308 BrtCellIsst */ | ||||
| @ -7618,6 +7674,12 @@ function parse_BrtCellIsst(data, length) { | ||||
| 	var isst = data.read_shift(4); | ||||
| 	return [cell, isst, 's']; | ||||
| } | ||||
| function write_BrtCellIsst(cell, ncell, o) { | ||||
| 	if(o == null) o = new_buf(12); | ||||
| 	write_XLSBCell(ncell, o); | ||||
| 	o.write_shift(4, ncell.v); | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.310 BrtCellReal */ | ||||
| function parse_BrtCellReal(data, length) { | ||||
| @ -7625,6 +7687,12 @@ function parse_BrtCellReal(data, length) { | ||||
| 	var value = parse_Xnum(data); | ||||
| 	return [cell, value, 'n']; | ||||
| } | ||||
| function write_BrtCellReal(cell, ncell, o) { | ||||
| 	if(o == null) o = new_buf(16); | ||||
| 	write_XLSBCell(ncell, o); | ||||
| 	write_Xnum(cell.v, o); | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.311 BrtCellRk */ | ||||
| function parse_BrtCellRk(data, length) { | ||||
| @ -7632,6 +7700,13 @@ function parse_BrtCellRk(data, length) { | ||||
| 	var value = parse_RkNumber(data); | ||||
| 	return [cell, value, 'n']; | ||||
| } | ||||
| function write_BrtCellRk(cell, ncell, o) { | ||||
| 	if(o == null) o = new_buf(12); | ||||
| 	write_XLSBCell(ncell, o); | ||||
| 	write_RkNumber(cell.v, o); | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.314 BrtCellSt */ | ||||
| function parse_BrtCellSt(data, length) { | ||||
| @ -7639,6 +7714,12 @@ function parse_BrtCellSt(data, length) { | ||||
| 	var value = parse_XLWideString(data); | ||||
| 	return [cell, value, 'str']; | ||||
| } | ||||
| function write_BrtCellSt(cell, ncell, o) { | ||||
| 	if(o == null) o = new_buf(12 + 4 * cell.v.length); | ||||
| 	write_XLSBCell(ncell, o); | ||||
| 	write_XLWideString(cell.v, o); | ||||
| 	return o.length > o.l ? o.slice(0, o.l) : o; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.647 BrtFmlaBool */ | ||||
| function parse_BrtFmlaBool(data, length, opts) { | ||||
| @ -7714,12 +7795,13 @@ function parse_ws_bin(data, opts, rels) { | ||||
| 	var s = {}; | ||||
| 
 | ||||
| 	var ref; | ||||
| 	var refguess = {s: {r:1000000, c:1000000}, e: {r:0, c:0} }; | ||||
| 	var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} }; | ||||
| 
 | ||||
| 	var pass = false, end = false; | ||||
| 	var row, p, cf, R, C, addr, sstr, rr; | ||||
| 	var mergecells = []; | ||||
| 	recordhopper(data, function ws_parse(val, R) { | ||||
| 		//console.log(R);
 | ||||
| 		if(end) return; | ||||
| 		switch(R.n) { | ||||
| 			case 'BrtWsDim': ref = val; break; | ||||
| @ -7896,7 +7978,7 @@ function parse_ws_bin(data, opts, rels) { | ||||
| 			default: if(!pass || opts.WTF) throw new Error("Unexpected record " + R.n); | ||||
| 		} | ||||
| 	}, opts); | ||||
| 	if(!s["!ref"] && (refguess.s.r < 1000000 || ref.e.r > 0 || ref.e.c > 0 || ref.s.r > 0 || ref.s.c > 0)) s["!ref"] = encode_range(ref); | ||||
| 	if(!s["!ref"] && (refguess.s.r < 2000000 || ref.e.r > 0 || ref.e.c > 0 || ref.s.r > 0 || ref.s.c > 0)) s["!ref"] = encode_range(ref); | ||||
| 	if(opts.sheetRows && s["!ref"]) { | ||||
| 		var tmpref = safe_decode_range(s["!ref"]); | ||||
| 		if(opts.sheetRows < +tmpref.e.r) { | ||||
| @ -7929,12 +8011,23 @@ function write_ws_bin_cell(ba, cell, R, C, opts) { | ||||
| 		case 's': case 'str': | ||||
| 			if(opts.bookSST) { | ||||
| 				vv = get_sst_id(opts.Strings, cell.v); | ||||
| 				o.t = "s"; break; | ||||
| 				o.t = "s"; o.v = vv; | ||||
| 				write_record(ba, "BrtCellIsst", write_BrtCellIsst(cell, o)); | ||||
| 			} else { | ||||
| 				o.t = "str"; | ||||
| 				write_record(ba, "BrtCellSt", write_BrtCellSt(cell, o)); | ||||
| 			} | ||||
| 			o.t = "str"; break; | ||||
| 		case 'n': break; | ||||
| 		case 'b': o.t = "b"; break; | ||||
| 		case 'e': o.t = "e"; break; | ||||
| 			return; | ||||
| 		case 'n': | ||||
| 			/* TODO: determine threshold for Real vs RK */ | ||||
| 			if(cell.v == (cell.v | 0) && cell.v > -1000 && cell.v < 1000) write_record(ba, "BrtCellRk", write_BrtCellRk(cell, o)); | ||||
| 			else write_record(ba, "BrtCellReal", write_BrtCellReal(cell, o)); | ||||
| 			return; | ||||
| 		case 'b': | ||||
| 			o.t = "b"; | ||||
| 			write_record(ba, "BrtCellBool", write_BrtCellBool(cell, o)); | ||||
| 			return; | ||||
| 		case 'e': /* TODO: error */ o.t = "e"; break; | ||||
| 	} | ||||
| 	write_record(ba, "BrtCellBlank", write_BrtCellBlank(cell, o)); | ||||
| } | ||||
| @ -7946,6 +8039,7 @@ function write_CELLTABLE(ba, ws, idx, opts, wb) { | ||||
| 		rr = encode_row(R); | ||||
| 		/* [ACCELLTABLE] */ | ||||
| 		/* BrtRowHdr */ | ||||
| 		write_row_header(ba, ws, range, R); | ||||
| 		for(var C = range.s.c; C <= range.e.c; ++C) { | ||||
| 			/* *16384CELL */ | ||||
| 			if(R === range.s.r) cols[C] = encode_col(C); | ||||
| @ -8258,7 +8352,7 @@ function write_BrtBundleSh(data, o) { | ||||
| 	o.write_shift(4, data.iTabID); | ||||
| 	write_RelID(data.strRelID, o); | ||||
| 	write_XLWideString(data.name.substr(0,31), o); | ||||
| 	return o; | ||||
| 	return o.length > o.l ? o.slice(0, o.l) : o; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.807 BrtWbProp */ | ||||
| @ -8366,7 +8460,7 @@ function write_BrtFileVersion(data, o) { | ||||
| 	write_XLWideString(XLSX.version, o); | ||||
| 	write_XLWideString("7262", o); | ||||
| 	o.length = o.l; | ||||
| 	return o; | ||||
| 	return o.length > o.l ? o.slice(0, o.l) : o; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.1.7.60 Workbook */ | ||||
| @ -8389,6 +8483,7 @@ function write_BrtCalcProp(data, o) { | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.640 BrtFileRecover */ | ||||
| function write_BrtFileRecover(data, o) { | ||||
| 	if(!o) o = new_buf(1); | ||||
| 	o.write_shift(1,0); | ||||
| @ -8401,22 +8496,22 @@ function write_wb_bin(wb, opts) { | ||||
| 	write_record(ba, "BrtBeginBook"); | ||||
| 	write_record(ba, "BrtFileVersion", write_BrtFileVersion()); | ||||
| 	/* [[BrtFileSharingIso] BrtFileSharing] */ | ||||
| 	write_record(ba, "BrtWbProp", write_BrtWbProp()); | ||||
| 	if(0) write_record(ba, "BrtWbProp", write_BrtWbProp()); | ||||
| 	/* [ACABSPATH] */ | ||||
| 	/* [[BrtBookProtectionIso] BrtBookProtection] */ | ||||
| 	write_BOOKVIEWS(ba, wb, opts); | ||||
| 	if(0) write_BOOKVIEWS(ba, wb, opts); | ||||
| 	write_BUNDLESHS(ba, wb, opts); | ||||
| 	/* [FNGROUP] */ | ||||
| 	/* [EXTERNALS] */ | ||||
| 	/* *BrtName */ | ||||
| 	write_record(ba, "BrtCalcProp", write_BrtCalcProp()); | ||||
| 	if(0) write_record(ba, "BrtCalcProp", write_BrtCalcProp()); | ||||
| 	/* [BrtOleSize] */ | ||||
| 	/* *(BrtUserBookView *FRT) */ | ||||
| 	/* [PIVOTCACHEIDS] */ | ||||
| 	/* [BrtWbFactoid] */ | ||||
| 	/* [SMARTTAGTYPES] */ | ||||
| 	/* [BrtWebOpt] */ | ||||
| 	write_record(ba, "BrtFileRecover", write_BrtFileRecover()); | ||||
| 	if(0) write_record(ba, "BrtFileRecover", write_BrtFileRecover()); | ||||
| 	/* [WEBPUBITEMS] */ | ||||
| 	/* [CRERRS] */ | ||||
| 	/* FRTWORKBOOK */ | ||||
| @ -8625,7 +8720,7 @@ function parse_xlml_xml(d, opts) { | ||||
| 	var sheets = {}, sheetnames = [], cursheet = {}, sheetname = ""; | ||||
| 	var table = {}, cell = {}, row = {}, dtag, didx; | ||||
| 	var c = 0, r = 0; | ||||
| 	var refguess = {s: {r:1000000, c:1000000}, e: {r:0, c:0} }; | ||||
| 	var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} }; | ||||
| 	var styles = {}, stag = {}; | ||||
| 	var ss = "", fidx = 0; | ||||
| 	var mergecells = []; | ||||
| @ -8685,7 +8780,7 @@ function parse_xlml_xml(d, opts) { | ||||
| 				if(mergecells.length) cursheet["!merges"] = mergecells; | ||||
| 				sheets[sheetname] = cursheet; | ||||
| 			} else { | ||||
| 				refguess = {s: {r:1000000, c:1000000}, e: {r:0, c:0} }; | ||||
| 				refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} }; | ||||
| 				r = c = 0; | ||||
| 				state.push([Rn[3], false]); | ||||
| 				tmp = xlml_parsexmltag(Rn[0]); | ||||
| @ -11080,12 +11175,17 @@ var XLSRecordEnum = { | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| /* Helper function to call out to ODS parser */ | ||||
| /* Helper functions to call out to ODS */ | ||||
| function parse_ods(zip, opts) { | ||||
| 	if(typeof module !== "undefined" && typeof require !== 'undefined' && typeof ODS === 'undefined') ODS = require('./od' + 's'); | ||||
| 	if(typeof ODS === 'undefined' || !ODS.parse_ods) throw new Error("Unsupported ODS"); | ||||
| 	return ODS.parse_ods(zip, opts); | ||||
| } | ||||
| function write_ods(wb, opts) { | ||||
| 	if(typeof module !== "undefined" && typeof require !== 'undefined' && typeof ODS === 'undefined') ODS = require('./od' + 's'); | ||||
| 	if(typeof ODS === 'undefined' || !ODS.write_ods) throw new Error("Unsupported ODS"); | ||||
| 	return ODS.write_ods(wb, opts); | ||||
| } | ||||
| function fix_opts_func(defaults) { | ||||
| 	return function fix_opts(opts) { | ||||
| 		for(var i = 0; i != defaults.length; ++i) { | ||||
| @ -11124,6 +11224,8 @@ var fix_write_opts = fix_opts_func([ | ||||
| 
 | ||||
| 	['bookType', 'xlsx'], /* Type of workbook (xlsx/m/b) */ | ||||
| 
 | ||||
| 	['compression', false], /* Use file compression */ | ||||
| 
 | ||||
| 	['WTF', false] /* WTF mode (throws errors) */ | ||||
| ]); | ||||
| function safe_parse_wbrels(wbrels, sheets) { | ||||
| @ -11278,6 +11380,7 @@ function add_rels(rels, rId, f, type, relobj) { | ||||
| } | ||||
| 
 | ||||
| function write_zip(wb, opts) { | ||||
| 	if(opts.bookType == "ods") return write_ods(wb, opts); | ||||
| 	if(wb && !wb.SSF) { | ||||
| 		wb.SSF = SSF.get_table(); | ||||
| 	} | ||||
| @ -11405,13 +11508,17 @@ function readFileSync(data, opts) { | ||||
| function write_zip_type(wb, opts) { | ||||
| 	var o = opts||{}; | ||||
| 	var z = write_zip(wb, o); | ||||
| 	var oopts = {}; | ||||
| 	if(opts.compression) oopts.compression = 'DEFLATE'; | ||||
| 	switch(o.type) { | ||||
| 		case "base64": return z.generate({type:"base64"}); | ||||
| 		case "binary": return z.generate({type:"string"}); | ||||
| 		case "buffer": return z.generate({type:"nodebuffer"}); | ||||
| 		case "file": return _fs.writeFileSync(o.file, z.generate({type:"nodebuffer"})); | ||||
| 		case "base64": oopts.type = "base64"; break; | ||||
| 		case "binary": oopts.type = "string"; break; | ||||
| 		case "buffer": | ||||
| 		case "file": oopts.type = "nodebuffer"; break; | ||||
| 		default: throw new Error("Unrecognized type " + o.type); | ||||
| 	} | ||||
| 	if(o.type === "file") return _fs.writeFileSync(o.file, z.generate(oopts)); | ||||
| 	return z.generate(oopts); | ||||
| } | ||||
| 
 | ||||
| function writeSync(wb, opts) { | ||||
| @ -11425,13 +11532,14 @@ function writeSync(wb, opts) { | ||||
| function writeFileSync(wb, filename, opts) { | ||||
| 	var o = opts||{}; o.type = 'file'; | ||||
| 	o.file = filename; | ||||
| 	switch(o.file.substr(-5).toLowerCase()) { | ||||
| 	if(!o.bookType) switch(o.file.substr(-5).toLowerCase()) { | ||||
| 		case '.xlsx': o.bookType = 'xlsx'; break; | ||||
| 		case '.xlsm': o.bookType = 'xlsm'; break; | ||||
| 		case '.xlsb': o.bookType = 'xlsb'; break; | ||||
| 	default: switch(o.file.substr(-4).toLowerCase()) { | ||||
| 		case '.xls': o.bookType = 'xls'; break; | ||||
| 		case '.xml': o.bookType = 'xml'; break; | ||||
| 		case '.ods': o.bookType = 'ods'; break; | ||||
| 	}} | ||||
| 	return writeSync(wb, o); | ||||
| } | ||||
|  | ||||
							
								
								
									
										19
									
								
								xlsxworker.flow.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										19
									
								
								xlsxworker.flow.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| /* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */ | ||||
| /* uncomment the next line for encoding support */ | ||||
| /*:: declare var XLSX: XLSXModule; */ | ||||
| /*:: declare var self: DedicatedWorkerGlobalScope; */ | ||||
| //importScripts('dist/cpexcel.js');
 | ||||
| importScripts('jszip.js'); | ||||
| importScripts('xlsx.js'); | ||||
| /* uncomment the next line for ODS support */ | ||||
| importScripts('dist/ods.js'); | ||||
| /*::self.*/postMessage({t:"ready"}); | ||||
| 
 | ||||
| onmessage = function (oEvent) { | ||||
|   var v; | ||||
|   try { | ||||
|     v = XLSX.read(oEvent.data.d, {type: oEvent.data.b ? 'binary' : 'base64'}); | ||||
|   } catch(e) { /*::self.*/postMessage({t:"e",d:e.stack||e}); } | ||||
|   /*::self.*/ | ||||
|   postMessage({t:"xlsx", d:JSON.stringify(v)}); | ||||
| }; | ||||
| @ -12,5 +12,5 @@ onmessage = function (oEvent) { | ||||
|   try { | ||||
|     v = XLSX.read(oEvent.data.d, {type: oEvent.data.b ? 'binary' : 'base64'}); | ||||
|   } catch(e) { postMessage({t:"e",d:e.stack||e}); } | ||||
|   postMessage({t:"xlsx", d:JSON.stringify(v)}); | ||||
| postMessage({t:"xlsx", d:JSON.stringify(v)}); | ||||
| }; | ||||
|  | ||||
							
								
								
									
										34
									
								
								xlsxworker1.flow.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										34
									
								
								xlsxworker1.flow.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | ||||
| /* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */ | ||||
| /* uncomment the next line for encoding support */ | ||||
| /*:: declare var XLSX: XLSXModule; */ | ||||
| /*:: declare var self: DedicatedWorkerGlobalScope; */ | ||||
| //importScripts('dist/cpexcel.js');
 | ||||
| importScripts('jszip.js'); | ||||
| importScripts('xlsx.js'); | ||||
| /* uncomment the next line for ODS support */ | ||||
| importScripts('dist/ods.js'); | ||||
| /*::self.*/postMessage({t:"ready"}); | ||||
| 
 | ||||
| function ab2str(data) { | ||||
| 	var o = "", l = 0, w = 10240; | ||||
| 	for(; l<data.byteLength/w; ++l) o+=String.fromCharCode.apply(null,/*::(*/new Uint16Array(data.slice(l*w,l*w+w))/*:: :any)*/); | ||||
| 	o+=String.fromCharCode.apply(null, /*::(*/new Uint16Array(data.slice(l*w))/*:: :any)*/); | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| function s2ab(s/*:string*/) { | ||||
|   var b = new ArrayBuffer(s.length*2), v = new Uint16Array(b); | ||||
|   for (var i=0; i != s.length; ++i) v[i] = s.charCodeAt(i); | ||||
|   return [v, b]; | ||||
| } | ||||
| 
 | ||||
| onmessage = function (oEvent) { | ||||
|   var v; | ||||
|   try { | ||||
|     v = XLSX.read(ab2str(oEvent.data), {type: 'binary'}); | ||||
|   } catch(e) { /*::self.*/postMessage({t:"e",d:e.stack}); } | ||||
|   var res = {t:"xlsx", d:JSON.stringify(v)}; | ||||
|   var r = s2ab(res.d)[1]; | ||||
|   /*::self.*/ | ||||
|   postMessage(r, [r]); | ||||
| }; | ||||
| @ -9,8 +9,8 @@ postMessage({t:"ready"}); | ||||
| 
 | ||||
| function ab2str(data) { | ||||
| 	var o = "", l = 0, w = 10240; | ||||
| 	for(; l<data.byteLength/w; ++l) o+=String.fromCharCode.apply(null,new Uint8Array(data.slice(l*w,l*w+w))); | ||||
| 	o+=String.fromCharCode.apply(null, new Uint8Array(data.slice(l*w))); | ||||
| 	for(; l<data.byteLength/w; ++l) o+=String.fromCharCode.apply(null,new Uint16Array(data.slice(l*w,l*w+w))); | ||||
| 	o+=String.fromCharCode.apply(null, new Uint16Array(data.slice(l*w))); | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| @ -27,5 +27,5 @@ onmessage = function (oEvent) { | ||||
|   } catch(e) { postMessage({t:"e",d:e.stack}); } | ||||
|   var res = {t:"xlsx", d:JSON.stringify(v)}; | ||||
|   var r = s2ab(res.d)[1]; | ||||
|   postMessage(r, [r]); | ||||
| postMessage(r, [r]); | ||||
| }; | ||||
|  | ||||
							
								
								
									
										34
									
								
								xlsxworker2.flow.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										34
									
								
								xlsxworker2.flow.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | ||||
| /* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */ | ||||
| /* uncomment the next line for encoding support */ | ||||
| /*:: declare var XLSX: XLSXModule; */ | ||||
| /*:: declare var self: DedicatedWorkerGlobalScope; */ | ||||
| //importScripts('dist/cpexcel.js');
 | ||||
| importScripts('jszip.js'); | ||||
| importScripts('xlsx.js'); | ||||
| /* uncomment the next line for ODS support */ | ||||
| importScripts('dist/ods.js'); | ||||
| /*::self.*/postMessage({t:"ready"}); | ||||
| 
 | ||||
| function ab2str(data) { | ||||
| 	var o = "", l = 0, w = 10240; | ||||
| 	for(; l<data.byteLength/w; ++l) o+=String.fromCharCode.apply(null,/*::(*/new Uint16Array(data.slice(l*w,l*w+w))/*:: :any)*/); | ||||
| 	o+=String.fromCharCode.apply(null, /*::(*/new Uint16Array(data.slice(l*w))/*:: :any)*/); | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| function s2ab(s/*:string*/) { | ||||
|   var b = new ArrayBuffer(s.length*2), v = new Uint16Array(b); | ||||
|   for (var i=0; i != s.length; ++i) v[i] = s.charCodeAt(i); | ||||
|   return [v, b]; | ||||
| } | ||||
| 
 | ||||
| onmessage = function (oEvent) { | ||||
|   var v; | ||||
|   try { | ||||
|     v = XLSX.read(ab2str(oEvent.data), {type: 'binary'}); | ||||
|   } catch(e) { /*::self.*/postMessage({t:"e",d:e.stack}); } | ||||
|   var res = {t:"xlsx", d:JSON.stringify(v)}; | ||||
|   var r = s2ab(res.d)[1]; | ||||
|   /*::self.*/ | ||||
|   postMessage(r, [r]); | ||||
| }; | ||||
| @ -27,5 +27,5 @@ onmessage = function (oEvent) { | ||||
|   } catch(e) { postMessage({t:"e",d:e.stack}); } | ||||
|   var res = {t:"xlsx", d:JSON.stringify(v)}; | ||||
|   var r = s2ab(res.d)[1]; | ||||
|   postMessage(r, [r]); | ||||
| postMessage(r, [r]); | ||||
| }; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user