forked from sheetjs/sheetjs
		
	version bump 0.11.16: refresh
- HTML whitespace (fixes #849 h/t @laurentauthier) - XLML number format write (fixes #904 h/t @james-boswell) - XLAM/XLA write - 'array' write type - XLSX/XLSB/XLS/XLML RTL read/write - XLS merge cells write - demo and typing refresh
This commit is contained in:
		
							parent
							
								
									33f96fc6ae
								
							
						
					
					
						commit
						f277ebe140
					
				| @ -14,8 +14,8 @@ tmp | ||||
| *.[pP][rR][nN] | ||||
| *.[sS][lL][kK] | ||||
| *.socialcalc | ||||
| *.[xX][lL][sSwWcC] | ||||
| *.[xX][lL][sS][xXmMbB] | ||||
| *.[xX][lL][sSwWcCaAtT] | ||||
| *.[xX][lL][sSaAtT][xXmMbB] | ||||
| *.[oO][dD][sS] | ||||
| *.[fF][oO][dD][sS] | ||||
| *.[xX][mM][lL] | ||||
|  | ||||
| @ -53,6 +53,7 @@ weex | ||||
| 
 | ||||
| # Other terms | ||||
| APIs | ||||
| ArrayBuffer | ||||
| Base64 | ||||
| Booleans | ||||
| JS | ||||
|  | ||||
| @ -4,6 +4,11 @@ This log is intended to keep track of backwards-incompatible changes, including | ||||
| but not limited to API changes and file location changes.  Minor behavioral | ||||
| changes may not be included if they are not expected to break existing code. | ||||
| 
 | ||||
| ## 0.11.16 (2017-12-30) | ||||
| 
 | ||||
| * XLS ANSI/CP separation | ||||
| * 'array' write type and ArrayBuffer processing | ||||
| 
 | ||||
| ## 0.11.6 (2017-10-16) | ||||
| 
 | ||||
| * Semicolon-delimited files are detected | ||||
|  | ||||
							
								
								
									
										21
									
								
								README.md
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										21
									
								
								README.md
									
									
									
									
									
								
							| @ -84,6 +84,7 @@ enhancements, additional features by request, and dedicated support. | ||||
|     + [Workbook File Properties](#workbook-file-properties) | ||||
|   * [Workbook-Level Attributes](#workbook-level-attributes) | ||||
|     + [Defined Names](#defined-names) | ||||
|     + [Workbook Views](#workbook-views) | ||||
|     + [Miscellaneous Workbook Properties](#miscellaneous-workbook-properties) | ||||
|   * [Document Features](#document-features) | ||||
|     + [Formulae](#formulae) | ||||
| @ -621,19 +622,12 @@ example uses [FileSaver](https://github.com/eligrey/FileSaver.js/): | ||||
| 
 | ||||
| ```js | ||||
| /* bookType can be any supported output type */ | ||||
| var wopts = { bookType:'xlsx', bookSST:false, type:'binary' }; | ||||
| var wopts = { bookType:'xlsx', bookSST:false, type:'array' }; | ||||
| 
 | ||||
| var wbout = XLSX.write(workbook,wopts); | ||||
| 
 | ||||
| function s2ab(s) { | ||||
|   var buf = new ArrayBuffer(s.length); | ||||
|   var view = new Uint8Array(buf); | ||||
|   for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF; | ||||
|   return buf; | ||||
| } | ||||
| 
 | ||||
| /* the saveAs call downloads a file on the local machine */ | ||||
| saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), "test.xlsx"); | ||||
| saveAs(new Blob([wbout],{type:"application/octet-stream"}), "test.xlsx"); | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
| @ -1081,6 +1075,14 @@ Excel allows two sheet-scoped defined names to share the same name.  However, a | ||||
| sheet-scoped name cannot collide with a workbook-scope name.  Workbook writers | ||||
| may not enforce this constraint. | ||||
| 
 | ||||
| #### Workbook Views | ||||
| 
 | ||||
| `wb.Workbook.Views` is an array of workbook view objects which have the keys: | ||||
| 
 | ||||
| | Key             | Description                                         | | ||||
| |:----------------|:----------------------------------------------------| | ||||
| | `RTL`           | If true, display right-to-left                      | | ||||
| 
 | ||||
| #### Miscellaneous Workbook Properties | ||||
| 
 | ||||
| `wb.Workbook.WBProps` holds other workbook properties: | ||||
| @ -1693,6 +1695,7 @@ The `type` argument for `write` mirrors the `type` argument for `read`: | ||||
| | `"binary"` | string: binary string (byte `n` is `data.charCodeAt(n)`)        | | ||||
| | `"string"` | string: JS string (characters interpreted as UTF8)              | | ||||
| | `"buffer"` | nodejs Buffer                                                   | | ||||
| | `"array"`  | ArrayBuffer, fallback array of 8-bit unsigned int               | | ||||
| | `"file"`   | string: path of file that will be created (nodejs only)         | | ||||
| 
 | ||||
| ## Utility Functions | ||||
|  | ||||
| @ -19,12 +19,14 @@ program | ||||
| 	.option('-B, --xlsb', 'emit XLSB to <sheetname> or <file>.xlsb') | ||||
| 	.option('-M, --xlsm', 'emit XLSM to <sheetname> or <file>.xlsm') | ||||
| 	.option('-X, --xlsx', 'emit XLSX to <sheetname> or <file>.xlsx') | ||||
| 	.option('-I, --xlam', 'emit XLAM to <sheetname> or <file>.xlam') | ||||
| 	.option('-Y, --ods',  'emit ODS  to <sheetname> or <file>.ods') | ||||
| 	.option('-8, --xls',  'emit XLS  to <sheetname> or <file>.xls (BIFF8)') | ||||
| 	.option('-5, --biff5','emit XLS  to <sheetname> or <file>.xls (BIFF5)') | ||||
| 	//.option('-4, --biff4','emit XLS  to <sheetname> or <file>.xls (BIFF4)') | ||||
| 	//.option('-3, --biff3','emit XLS  to <sheetname> or <file>.xls (BIFF3)') | ||||
| 	.option('-2, --biff2','emit XLS  to <sheetname> or <file>.xls (BIFF2)') | ||||
| 	.option('-i, --xla', 'emit XLA to <sheetname> or <file>.xla') | ||||
| 	.option('-6, --xlml', 'emit SSML to <sheetname> or <file>.xls (2003 XML)') | ||||
| 	.option('-T, --fods', 'emit FODS to <sheetname> or <file>.fods (Flat ODS)') | ||||
| 
 | ||||
| @ -65,8 +67,10 @@ program.on('--help', function() { | ||||
| var workbook_formats = [ | ||||
| 	['xlsx',   'xlsx', 'xlsx'], | ||||
| 	['xlsm',   'xlsm', 'xlsm'], | ||||
| 	['xlam',   'xlam', 'xlam'], | ||||
| 	['xlsb',   'xlsb', 'xlsb'], | ||||
| 	['xls',     'xls',  'xls'], | ||||
| 	['xla',     'xla',  'xla'], | ||||
| 	['biff5', 'biff5',  'xls'], | ||||
| 	['ods',     'ods',  'ods'], | ||||
| 	['fods',   'fods', 'fods'] | ||||
|  | ||||
| @ -1 +1 @@ | ||||
| XLSX.version = '0.11.15'; | ||||
| XLSX.version = '0.11.16'; | ||||
|  | ||||
| @ -1,21 +1,51 @@ | ||||
| var current_codepage = 1200; | ||||
| var current_codepage = 1200, current_ansi = 1252; | ||||
| /*:: declare var cptable:any; */ | ||||
| /*global cptable:true */ | ||||
| if(typeof module !== "undefined" && typeof require !== 'undefined') { | ||||
| 	if(typeof cptable === 'undefined') global.cptable = require('./dist/cpexcel.js'); | ||||
| } | ||||
| function reset_cp() { set_cp(1200); } | ||||
| var set_cp = function(cp) { current_codepage = cp; }; | ||||
| 
 | ||||
| function char_codes(data) { var o = []; for(var i = 0, len = data.length; i < len; ++i) o[i] = data.charCodeAt(i); return o; } | ||||
| var VALID_ANSI = [ 874, 932, 936, 949, 950 ]; | ||||
| for(var i = 0; i <= 8; ++i) VALID_ANSI.push(1250 + i); | ||||
| /* ECMA-376 Part I 18.4.1 charset to codepage mapping */ | ||||
| var CS2CP = ({ | ||||
| 	/*::[*/0/*::]*/:    1252, /* ANSI */ | ||||
| 	/*::[*/1/*::]*/:   65001, /* DEFAULT */ | ||||
| 	/*::[*/2/*::]*/:   65001, /* SYMBOL */ | ||||
| 	/*::[*/77/*::]*/:  10000, /* MAC */ | ||||
| 	/*::[*/128/*::]*/:   932, /* SHIFTJIS */ | ||||
| 	/*::[*/129/*::]*/:   949, /* HANGUL */ | ||||
| 	/*::[*/130/*::]*/:  1361, /* JOHAB */ | ||||
| 	/*::[*/134/*::]*/:   936, /* GB2312 */ | ||||
| 	/*::[*/136/*::]*/:   950, /* CHINESEBIG5 */ | ||||
| 	/*::[*/161/*::]*/:  1253, /* GREEK */ | ||||
| 	/*::[*/162/*::]*/:  1254, /* TURKISH */ | ||||
| 	/*::[*/163/*::]*/:  1258, /* VIETNAMESE */ | ||||
| 	/*::[*/177/*::]*/:  1255, /* HEBREW */ | ||||
| 	/*::[*/178/*::]*/:  1256, /* ARABIC */ | ||||
| 	/*::[*/186/*::]*/:  1257, /* BALTIC */ | ||||
| 	/*::[*/204/*::]*/:  1251, /* RUSSIAN */ | ||||
| 	/*::[*/222/*::]*/:   874, /* THAI */ | ||||
| 	/*::[*/238/*::]*/:  1250, /* EASTEUROPE */ | ||||
| 	/*::[*/255/*::]*/:  1252, /* OEM */ | ||||
| 	/*::[*/69/*::]*/:   6969  /* MISC */ | ||||
| }/*:any*/); | ||||
| 
 | ||||
| var set_ansi = function(cp/*:number*/) { if(VALID_ANSI.indexOf(cp) == -1) return; current_ansi = CS2CP[0] = cp; }; | ||||
| function reset_ansi() { set_ansi(1252); } | ||||
| 
 | ||||
| var set_cp = function(cp/*:number*/) { current_codepage = cp; set_ansi(cp); }; | ||||
| function reset_cp() { set_cp(1200); reset_ansi(); } | ||||
| 
 | ||||
| function char_codes(data/*:string*/)/*:Array<number>*/ { var o/*:Array<number>*/ = []; for(var i = 0, len = data.length; i < len; ++i) o[i] = data.charCodeAt(i); return o; } | ||||
| 
 | ||||
| function utf16leread(data/*:string*/)/*:string*/ { | ||||
| 	var o = []; | ||||
| 	var o/*:Array<string>*/ = []; | ||||
| 	for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data.charCodeAt(2*i) + (data.charCodeAt(2*i+1)<<8)); | ||||
| 	return o.join(""); | ||||
| } | ||||
| function utf16beread(data/*:string*/)/*:string*/ { | ||||
| 	var o = []; | ||||
| 	var o/*:Array<string>*/ = []; | ||||
| 	for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data.charCodeAt(2*i+1) + (data.charCodeAt(2*i)<<8)); | ||||
| 	return o.join(""); | ||||
| } | ||||
|  | ||||
| @ -12,6 +12,18 @@ function s2a(s/*:string*/) { | ||||
| 	return s.split("").map(function(x){ return x.charCodeAt(0) & 0xff; }); | ||||
| } | ||||
| 
 | ||||
| function s2ab(s/*:string*/) { | ||||
| 	if(typeof ArrayBuffer === 'undefined') return s2a(s); | ||||
| 	var buf = new ArrayBuffer(s.length), view = new Uint8Array(buf); | ||||
| 	for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF; | ||||
| 	return buf; | ||||
| } | ||||
| 
 | ||||
| function arr2str(data/*:any*/)/*:string*/ { | ||||
| 	if(Array.isArray(data)) return data.map(_chr).join(""); | ||||
| 	var o/*:Array<string>*/ = []; for(var i = 0; i < data.length; ++i) o[i] = _chr(data[i]); return o.join(""); | ||||
| } | ||||
| 
 | ||||
| var bconcat = function(bufs) { return [].concat.apply([], bufs); }; | ||||
| 
 | ||||
| var chr0 = /\u0000/g, chr1 = /[\u0001-\u0006]/g; | ||||
|  | ||||
| @ -1,5 +1,3 @@ | ||||
| function isval(x/*:?any*/)/*:boolean*/ { return x !== undefined && x !== null; } | ||||
| 
 | ||||
| function keys(o/*:any*/)/*:Array<any>*/ { return Object.keys(o); } | ||||
| 
 | ||||
| function evert_key(obj/*:any*/, key/*:string*/)/*:EvertType*/ { | ||||
| @ -99,12 +97,6 @@ function cc2str(arr/*:Array<number>*/)/*:string*/ { | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| function str2cc(str) { | ||||
| 	var o = []; | ||||
| 	for(var i = 0; i != str.length; ++i) o.push(str.charCodeAt(i)); | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| function dup(o/*:any*/)/*:any*/ { | ||||
| 	if(typeof JSON != 'undefined' && !Array.isArray(o)) return JSON.parse(JSON.stringify(o)); | ||||
| 	if(typeof o != 'object' || o == null) return o; | ||||
|  | ||||
| @ -13,7 +13,7 @@ function getdatabin(data) { | ||||
| 	if(data.asNodeBuffer && has_buf) return data.asNodeBuffer(); | ||||
| 	if(data._data && data._data.getContent) { | ||||
| 		var o = data._data.getContent(); | ||||
| 		if(typeof o == "string") return str2cc(o); | ||||
| 		if(typeof o == "string") return char_codes(o); | ||||
| 		return Array.prototype.slice.call(o); | ||||
| 	} | ||||
| 	return null; | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n'; | ||||
| var attregexg=/([^"\s?>\/]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:')|([^'">\s]+))/g; | ||||
| var tagregex=/<[\/\?]?[a-zA-Z0-9:]+(?:\s+[^"\s?>\/]+=(?:"[^"]*"|'[^']*'|[^'">\s]+))*\s?[\/\?]?>/g; | ||||
| var attregexg=/([^"\s?>\/]+)\s*=\s*((?:")([^"]*)(?:")|(?:')([^']*)(?:')|([^'">\s]+))/g; | ||||
| var tagregex=/<[\/\?]?[a-zA-Z0-9:]+(?:\s+[^"\s?>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'">\s]+))*\s?[\/\?]?>/g; | ||||
| if(!(XML_HEADER.match(tagregex))) tagregex = /<[^>]*>/g; | ||||
| var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/; | ||||
| function parsexmltag(tag/*:string*/, skip_root/*:?boolean*/)/*:any*/ { | ||||
| @ -13,7 +13,8 @@ function parsexmltag(tag/*:string*/, skip_root/*:?boolean*/)/*:any*/ { | ||||
| 	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); | ||||
| 		q = cc.substr(0,c).trim(); | ||||
| 		while(cc.charCodeAt(c+1) == 32) ++c; | ||||
| 		quot = ((eq=cc.charCodeAt(c+1)) == 34 || eq == 39) ? 1 : 0; | ||||
| 		v = cc.substring(c+1+quot, cc.length-quot); | ||||
| 		for(j=0;j!=q.length;++j) if(q.charCodeAt(j) === 58) break; | ||||
| @ -84,7 +85,7 @@ function parsexmlbool(value/*:any*/, tag/*:?string*/)/*:boolean*/ { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| var utf8read/*:StringConv*/ = function utf8reada(orig) { | ||||
| var utf8read/*:StringConv*/ = function utf8reada(orig/*:string*/)/*:string*/ { | ||||
| 	var out = "", i = 0, c = 0, d = 0, e = 0, f = 0, w = 0; | ||||
| 	while (i < orig.length) { | ||||
| 		c = orig.charCodeAt(i++); | ||||
| @ -101,7 +102,7 @@ var utf8read/*:StringConv*/ = function utf8reada(orig) { | ||||
| 	return out; | ||||
| }; | ||||
| 
 | ||||
| var utf8write/*:StringConv*/ = function(orig) { | ||||
| var utf8write/*:StringConv*/ = function(orig/*:string*/)/*:string*/ { | ||||
| 	var out/*:Array<string>*/ = [], i = 0, c = 0, d = 0; | ||||
| 	while(i < orig.length) { | ||||
| 		c = orig.charCodeAt(i++); | ||||
| @ -156,18 +157,18 @@ if(has_buf) { | ||||
| // matches <foo>...</foo> extracts content
 | ||||
| var matchtag = (function() { | ||||
| 	var mtcache/*:{[k:string]:RegExp}*/ = ({}/*:any*/); | ||||
| 	return function matchtag(f,g/*:?string*/)/*:RegExp*/ { | ||||
| 	return function matchtag(f/*:string*/,g/*:?string*/)/*:RegExp*/ { | ||||
| 		var t = f+"|"+(g||""); | ||||
| 		if(mtcache[t]) return mtcache[t]; | ||||
| 		return (mtcache[t] = new RegExp('<(?:\\w+:)?'+f+'(?: xml:space="preserve")?(?:[^>]*)>([\\s\\S]*?)</(?:\\w+:)?'+f+'>',((g||"")/*:any*/))); | ||||
| 	}; | ||||
| })(); | ||||
| 
 | ||||
| var htmldecode = (function() { | ||||
| 	var entities = [ | ||||
| var htmldecode/*:{(s:string):string}*/ = (function() { | ||||
| 	var entities/*:Array<[RegExp, string]>*/ = [ | ||||
| 		['nbsp', ' '], ['middot', '·'], | ||||
| 		['quot', '"'], ['apos', "'"], ['gt',   '>'], ['lt',   '<'], ['amp',  '&'] | ||||
| 	].map(function(x) { return [new RegExp('&' + x[0] + ';', "g"), x[1]]; }); | ||||
| 	].map(function(x/*:[string, string]*/) { return [new RegExp('&' + x[0] + ';', "g"), x[1]]; }); | ||||
| 	return function htmldecode(str/*:string*/)/*:string*/ { | ||||
| 		var o = str.trim().replace(/\s+/g, " ").replace(/<\s*[bB][rR]\s*\/?>/g,"\n").replace(/<[^>]*>/g,""); | ||||
| 		for(var i = 0; i < entities.length; ++i) o = o.replace(entities[i][0], entities[i][1]); | ||||
| @ -181,27 +182,27 @@ var vtregex = (function(){ var vt_cache = {}; | ||||
| 		return (vt_cache[bt] = new RegExp("<(?:vt:)?" + bt + ">([\\s\\S]*?)</(?:vt:)?" + bt + ">", 'g') ); | ||||
| };})(); | ||||
| var vtvregex = /<\/?(?:vt:)?variant>/g, vtmregex = /<(?:vt:)([^>]*)>([\s\S]*)</; | ||||
| function parseVector(data, opts) { | ||||
| function parseVector(data/*:string*/, opts)/*:Array<{v:string,t:string}>*/ { | ||||
| 	var h = parsexmltag(data); | ||||
| 
 | ||||
| 	var matches = data.match(vtregex(h.baseType))||[]; | ||||
| 	var res = []; | ||||
| 	var matches/*:Array<string>*/ = data.match(vtregex(h.baseType))||[]; | ||||
| 	var res/*:Array<any>*/ = []; | ||||
| 	if(matches.length != h.size) { | ||||
| 		if(opts.WTF) throw new Error("unexpected vector length " + matches.length + " != " + h.size); | ||||
| 		return res; | ||||
| 	} | ||||
| 	matches.forEach(function(x) { | ||||
| 	matches.forEach(function(x/*:string*/) { | ||||
| 		var v = x.replace(vtvregex,"").match(vtmregex); | ||||
| 		res.push({v:utf8read(v[2]), t:v[1]}); | ||||
| 		if(v) res.push({v:utf8read(v[2]), t:v[1]}); | ||||
| 	}); | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| var wtregex = /(^\s|\s$|\n)/; | ||||
| function writetag(f,g) {return '<' + f + (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f + '>';} | ||||
| function writetag(f/*:string*/,g/*:string*/)/*:string*/ { return '<' + f + (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f + '>'; } | ||||
| 
 | ||||
| function wxt_helper(h)/*:string*/ { return keys(h).map(function(k) { return " " + k + '="' + h[k] + '"';}).join(""); } | ||||
| function writextag(f,g,h) { return '<' + f + (isval(h) /*:: && h */? wxt_helper(h) : "") + (isval(g) /*:: && g */? (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f : "/") + '>';} | ||||
| function writextag(f/*:string*/,g/*:?string*/,h) { return '<' + f + ((h != null) ? wxt_helper(h) : "") + ((g != null) ? (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f : "/") + '>';} | ||||
| 
 | ||||
| function write_w3cdtf(d/*:Date*/, t/*:?boolean*/)/*:string*/ { try { return d.toISOString().replace(/\.\d*/,""); } catch(e) { if(t) throw e; } return ""; } | ||||
| 
 | ||||
|  | ||||
| @ -35,6 +35,8 @@ var __utf8 = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { var ss= | ||||
| var ___utf8 = __utf8; | ||||
| var __lpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";}; | ||||
| var ___lpstr = __lpstr; | ||||
| var __cpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";}; | ||||
| var ___cpstr = __cpstr; | ||||
| var __lpwstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = 2*__readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";}; | ||||
| var ___lpwstr = __lpwstr; | ||||
| var __lpp4, ___lpp4; | ||||
| @ -49,6 +51,7 @@ if(has_buf/*:: && typeof Buffer !== 'undefined'*/) { | ||||
| 	__utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/)/*:string*/ { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___utf16le(b,s,e); return b.toString('utf16le',s,e).replace(chr0,'')/*.replace(chr1,'!')*/; }; | ||||
| 	__hexlify = function(b/*:RawBytes|CFBlob*/,s/*:number*/,l/*:number*/)/*:string*/ { return Buffer.isBuffer(b)/*:: && b instanceof Buffer*/ ? b.toString('hex',s,s+l) : ___hexlify(b,s,l); }; | ||||
| 	__lpstr = function lpstr_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___lpstr(b, i); var len = b.readUInt32LE(i); return len > 0 ? b.toString('utf8',i+4,i+4+len-1) : "";}; | ||||
| 	__cpstr = function cpstr_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___cpstr(b, i); var len = b.readUInt32LE(i); return len > 0 ? b.toString('utf8',i+4,i+4+len-1) : "";}; | ||||
| 	__lpwstr = function lpwstr_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___lpwstr(b, i); var len = 2*b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len-1);}; | ||||
| 	__lpp4 = function lpp4_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len);}; | ||||
| 	__8lpp4 = function lpp4_8b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___8lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf8',i+4,i+4+len);}; | ||||
| @ -63,7 +66,8 @@ if(has_buf/*:: && typeof Buffer !== 'undefined'*/) { | ||||
| if(typeof cptable !== 'undefined') { | ||||
| 	__utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { return cptable.utils.decode(1200, b.slice(s,e)).replace(chr0, ''); }; | ||||
| 	__utf8 = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { return cptable.utils.decode(65001, b.slice(s,e)); }; | ||||
| 	__lpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(current_codepage, b.slice(i+4, i+4+len-1)) : "";}; | ||||
| 	__lpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(current_ansi, b.slice(i+4, i+4+len-1)) : "";}; | ||||
| 	__cpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(current_codepage, b.slice(i+4, i+4+len-1)) : "";}; | ||||
| 	__lpwstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = 2*__readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(1200, b.slice(i+4,i+4+len-1)) : "";}; | ||||
| 	__lpp4 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(1200, b.slice(i+4,i+4+len)) : "";}; | ||||
| 	__8lpp4 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(65001, b.slice(i+4,i+4+len)) : "";}; | ||||
| @ -98,9 +102,10 @@ function ReadShift(size/*:number*/, t/*:?string*/)/*:number|string*/ { | ||||
| 			size = 2 * size; break; | ||||
| 
 | ||||
| 		/* [MS-OLEDS] 2.1.4 LengthPrefixedAnsiString */ | ||||
| 		case 'lpstr': o = __lpstr(this, this.l); size = 5 + o.length; break; | ||||
| 		case 'lpstr-ansi': o = __lpstr(this, this.l); size = 4 + __readUInt32LE(this, this.l); break; | ||||
| 		case 'lpstr-cp': o = __cpstr(this, this.l); size = 4 + __readUInt32LE(this, this.l); break; | ||||
| 		/* [MS-OLEDS] 2.1.5 LengthPrefixedUnicodeString */ | ||||
| 		case 'lpwstr': o = __lpwstr(this, this.l); size = 5 + o.length; if(o[o.length-1] == '\u0000') size += 2; break; | ||||
| 		case 'lpwstr': o = __lpwstr(this, this.l); size = 4 + 2 * __readUInt32LE(this, this.l); break; | ||||
| 		/* [MS-OFFCRYPTO] 2.1.2 Length-Prefixed Padded Unicode String (UNICODE-LP-P4) */ | ||||
| 		case 'lpp4': size = 4 +  __readUInt32LE(this, this.l); o = __lpp4(this, this.l); if(size & 0x02) size += 2; break; | ||||
| 		/* [MS-OFFCRYPTO] 2.1.3 Length-Prefixed UTF-8 String (UTF-8-LP-P4) */ | ||||
| @ -222,9 +227,6 @@ function prep_blob(blob, pos/*:number*/)/*:void*/ { | ||||
| } | ||||
| 
 | ||||
| function parsenoop(blob, length/*:: :number, opts?:any */) { blob.l += length; } | ||||
| function parsenooplog(blob, length/*:number*/) { if(typeof console != 'undefined') console.log(blob.slice(blob.l, blob.l + length)); blob.l += length; } | ||||
| 
 | ||||
| function writenoop(blob, length/*:number*/) { blob.l += length; } | ||||
| 
 | ||||
| function new_buf(sz/*:number*/)/*:Block*/ { | ||||
| 	var o = new_raw_buf(sz); | ||||
|  | ||||
| @ -20,14 +20,14 @@ function recordhopper(data, cb/*:RecordHopperCB*/, opts/*:?any*/) { | ||||
| 
 | ||||
| /* control buffer usage for fixed-length buffers */ | ||||
| function buf_array()/*:BufArray*/ { | ||||
| 	var bufs = [], blksz = has_buf ? 256 : 2048; | ||||
| 	var newblk = function ba_newblk(sz) { | ||||
| 	var bufs/*:Array<Block>*/ = [], blksz = has_buf ? 256 : 2048; | ||||
| 	var newblk = function ba_newblk(sz/*:number*/)/*:Block*/ { | ||||
| 		var o/*:Block*/ = (new_buf(sz)/*:any*/); | ||||
| 		prep_blob(o, 0); | ||||
| 		return o; | ||||
| 	}; | ||||
| 
 | ||||
| 	var curbuf = newblk(blksz); | ||||
| 	var curbuf/*:Block*/ = newblk(blksz); | ||||
| 
 | ||||
| 	var endbuf = function ba_endbuf() { | ||||
| 		if(!curbuf) return; | ||||
| @ -36,7 +36,7 @@ function buf_array()/*:BufArray*/ { | ||||
| 		curbuf = null; | ||||
| 	}; | ||||
| 
 | ||||
| 	var next = function ba_next(sz) { | ||||
| 	var next = function ba_next(sz/*:number*/)/*:Block*/ { | ||||
| 		if(curbuf && sz < curbuf.length - curbuf.l) return curbuf; | ||||
| 		endbuf(); | ||||
| 		return (curbuf = newblk(Math.max(sz+1, blksz))); | ||||
| @ -56,7 +56,7 @@ function write_record(ba/*:BufArray*/, type/*:string*/, payload, length/*:?numbe | ||||
| 	var t/*:number*/ = +XLSBRE[type], l; | ||||
| 	if(isNaN(t)) return; // TODO: throw something here?
 | ||||
| 	if(!length) length = XLSBRecordEnum[t].p || (payload||[]).length || 0; | ||||
| 	l = 1 + (t >= 0x80 ? 1 : 0) + 1 + length; | ||||
| 	l = 1 + (t >= 0x80 ? 1 : 0) + 1/* + length*/; | ||||
| 	if(length >= 0x80) ++l; if(length >= 0x4000) ++l; if(length >= 0x200000) ++l; | ||||
| 	var o = ba.next(l); | ||||
| 	if(t <= 0x7F) o.write_shift(1, t); | ||||
|  | ||||
| @ -265,3 +265,19 @@ function write_FontFlags(font, o) { | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| /* [MS-OLEDS] 2.3.1 and 2.3.2 */ | ||||
| function parse_ClipboardFormatOrString(o, w/*:number*/)/*:string*/ { | ||||
| 	// $FlowIgnore
 | ||||
| 	var ClipFmt = {2:"BITMAP",3:"METAFILEPICT",8:"DIB",14:"ENHMETAFILE"}; | ||||
| 	var m/*:number*/ = o.read_shift(4); | ||||
| 	switch(m) { | ||||
| 		case 0x00000000: return ""; | ||||
| 		case 0xffffffff: case 0xfffffffe: return ClipFmt[o.read_shift(4)]||""; | ||||
| 	} | ||||
| 	if(m > 0x190) throw new Error("Unsupported Clipboard: " + m.toString(16)); | ||||
| 	o.l -= 4; | ||||
| 	return o.read_shift(0, w == 1 ? "lpstr" : "lpwstr"); | ||||
| } | ||||
| function parse_ClipboardFormatOrAnsiString(o) { return parse_ClipboardFormatOrString(o, 1); } | ||||
| function parse_ClipboardFormatOrUnicodeString(o) { return parse_ClipboardFormatOrString(o, 2); } | ||||
| 
 | ||||
|  | ||||
| @ -87,7 +87,7 @@ var SummaryPIDSI = { | ||||
| 	/*::[*/0x0F/*::]*/: { n: 'WordCount', t: VT_I4 }, | ||||
| 	/*::[*/0x10/*::]*/: { n: 'CharCount', t: VT_I4 }, | ||||
| 	/*::[*/0x11/*::]*/: { n: 'Thumbnail', t: VT_CF }, | ||||
| 	/*::[*/0x12/*::]*/: { n: 'ApplicationName', t: VT_LPSTR }, | ||||
| 	/*::[*/0x12/*::]*/: { n: 'ApplicationName', t: VT_STRING }, | ||||
| 	/*::[*/0x13/*::]*/: { n: 'DocumentSecurity', t: VT_I4 }, | ||||
| 	/*::[*/0xFF/*::]*/: {} | ||||
| }; | ||||
|  | ||||
| @ -180,7 +180,7 @@ var CT_LIST = (function(){ | ||||
| 			xlsb: "application/vnd.ms-excel.styles" | ||||
| 		} | ||||
| 	}; | ||||
| 	keys(o).forEach(function(k) { if(!o[k].xlsm) o[k].xlsm = o[k].xlsx; }); | ||||
| 	keys(o).forEach(function(k) { ["xlsm", "xlam"].forEach(function(v) { if(!o[k][v]) o[k][v] = o[k].xlsx; }); }); | ||||
| 	keys(o).forEach(function(k){ keys(o[k]).forEach(function(v) { ct2type[o[k][v]] = k; }); }); | ||||
| 	return o; | ||||
| })(); | ||||
|  | ||||
| @ -84,7 +84,7 @@ var EXT_PROPS_XML_ROOT = writextag('Properties', null, { | ||||
| }); | ||||
| 
 | ||||
| function write_ext_props(cp, opts)/*:string*/ { | ||||
| 	var o = [], p = {}, W = writextag; | ||||
| 	var o/*:Array<string>*/ = [], p = {}, W = writextag; | ||||
| 	if(!cp) cp = {}; | ||||
| 	cp.Application = "SheetJS"; | ||||
| 	o[o.length] = (XML_HEADER); | ||||
|  | ||||
| @ -39,7 +39,7 @@ function xlml_set_prop(Props, tag/*:string*/, val) { | ||||
| } | ||||
| 
 | ||||
| function xlml_write_docprops(Props, opts) { | ||||
| 	var o = []; | ||||
| 	var o/*:Array<string>*/ = []; | ||||
| 	keys(XLMLDocPropsMap).map(function(m) { | ||||
| 		for(var i = 0; i < CORE_PROPS.length; ++i) if(CORE_PROPS[i][1] == m) return CORE_PROPS[i]; | ||||
| 		for(i = 0; i < EXT_PROPS.length; ++i) if(EXT_PROPS[i][1] == m) return EXT_PROPS[i]; | ||||
| @ -60,7 +60,7 @@ function xlml_write_docprops(Props, opts) { | ||||
| function xlml_write_custprops(Props, Custprops, opts) { | ||||
| 	var BLACKLIST = ["Worksheets","SheetNames"]; | ||||
| 	var T = 'CustomDocumentProperties'; | ||||
| 	var o = []; | ||||
| 	var o/*:Array<string>*/ = []; | ||||
| 	if(Props) keys(Props).forEach(function(k) { | ||||
| 		/*:: if(!Props) return; */ | ||||
| 		if(!Props.hasOwnProperty(k)) return; | ||||
|  | ||||
| @ -8,8 +8,9 @@ function parse_FILETIME(blob) { | ||||
| 
 | ||||
| /* [MS-OSHARED] 2.3.3.1.4 Lpstr */ | ||||
| function parse_lpstr(blob, type, pad/*:?number*/) { | ||||
| 	var str = blob.read_shift(0, 'lpstr'); | ||||
| 	if(pad) blob.l += (4 - ((str.length+1) & 3)) & 3; | ||||
| 	var start = blob.l; | ||||
| 	var str = blob.read_shift(0, 'lpstr-cp'); | ||||
| 	if(pad) while((blob.l - start) & 3) ++blob.l; | ||||
| 	return str; | ||||
| } | ||||
| 
 | ||||
| @ -32,15 +33,15 @@ function parse_VtString(blob, t/*:number*/, pad/*:?boolean*/) { return parse_VtS | ||||
| function parse_VtUnalignedString(blob, t/*:number*/) { if(!t) throw new Error("VtUnalignedString must have positive length"); return parse_VtStringBase(blob, t, 0); } | ||||
| 
 | ||||
| /* [MS-OSHARED] 2.3.3.1.9 VtVecUnalignedLpstrValue */ | ||||
| function parse_VtVecUnalignedLpstrValue(blob) { | ||||
| function parse_VtVecUnalignedLpstrValue(blob)/*:Array<string>*/ { | ||||
| 	var length = blob.read_shift(4); | ||||
| 	var ret = []; | ||||
| 	for(var i = 0; i != length; ++i) ret[i] = blob.read_shift(0, 'lpstr'); | ||||
| 	var ret/*:Array<string>*/ = []; | ||||
| 	for(var i = 0; i != length; ++i) ret[i] = blob.read_shift(0, 'lpstr-cp').replace(chr0,''); | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| /* [MS-OSHARED] 2.3.3.1.10 VtVecUnalignedLpstr */ | ||||
| function parse_VtVecUnalignedLpstr(blob) { | ||||
| function parse_VtVecUnalignedLpstr(blob)/*:Array<string>*/ { | ||||
| 	return parse_VtVecUnalignedLpstrValue(blob); | ||||
| } | ||||
| 
 | ||||
| @ -155,16 +156,17 @@ function parse_PropertySet(blob, PIDSI) { | ||||
| 		var Offset = blob.read_shift(4); | ||||
| 		Props[i] = [PropID, Offset + start_addr]; | ||||
| 	} | ||||
| 	Props.sort(function(x,y) { return x[1] - y[1]; }); | ||||
| 	var PropH = {}; | ||||
| 	for(i = 0; i != NumProps; ++i) { | ||||
| 		if(blob.l !== Props[i][1]) { | ||||
| 			var fail = true; | ||||
| 			if(i>0 && PIDSI) switch(PIDSI[Props[i-1][0]].t) { | ||||
| 				case 0x02 /*VT_I2*/: if(blob.l +2 === Props[i][1]) { blob.l+=2; fail = false; } break; | ||||
| 				case 0x02 /*VT_I2*/: if(blob.l+2 === Props[i][1]) { blob.l+=2; fail = false; } break; | ||||
| 				case 0x50 /*VT_STRING*/: if(blob.l <= Props[i][1]) { blob.l=Props[i][1]; fail = false; } break; | ||||
| 				case 0x100C /*VT_VECTOR|VT_VARIANT*/: if(blob.l <= Props[i][1]) { blob.l=Props[i][1]; fail = false; } break; | ||||
| 			} | ||||
| 			if(!PIDSI && blob.l <= Props[i][1]) { fail=false; blob.l = Props[i][1]; } | ||||
| 			if((!PIDSI||i==0) && blob.l <= Props[i][1]) { fail=false; blob.l = Props[i][1]; } | ||||
| 			if(fail) throw new Error("Read Error: Expected address " + Props[i][1] + ' at ' + blob.l + ' :' + i); | ||||
| 		} | ||||
| 		if(PIDSI) { | ||||
| @ -326,7 +328,7 @@ function parse_XLUnicodeRichExtendedString(blob) { | ||||
| 	var z = {}; | ||||
| 	if(fRichSt) cRun = blob.read_shift(2); | ||||
| 	if(fExtSt) cbExtRst = blob.read_shift(4); | ||||
| 	var encoding = (flags & 0x1) ? 'dbcs-cont' : 'sbcs-cont'; | ||||
| 	var encoding = width == 2 ? 'dbcs-cont' : 'sbcs-cont'; | ||||
| 	var msg = cch === 0 ? "" : blob.read_shift(cch, encoding); | ||||
| 	if(fRichSt) blob.l += 4 * cRun; //TODO: parse this
 | ||||
| 	if(fExtSt) blob.l += cbExtRst; //TODO: parse this
 | ||||
| @ -398,15 +400,14 @@ function parse_URLMoniker(blob/*::, length, opts*/) { | ||||
| /* [MS-OSHARED] 2.3.7.8 FileMoniker TODO: all fields */ | ||||
| function parse_FileMoniker(blob, length) { | ||||
| 	var cAnti = blob.read_shift(2); | ||||
| 	var ansiLength = blob.read_shift(4); | ||||
| 	var ansiPath = blob.read_shift(ansiLength, 'cstr'); | ||||
| 	var ansiPath = blob.read_shift(0, 'lpstr-ansi'); | ||||
| 	var endServer = blob.read_shift(2); | ||||
| 	var versionNumber = blob.read_shift(2); | ||||
| 	var cbUnicodePathSize = blob.read_shift(4); | ||||
| 	if(cbUnicodePathSize === 0) return ansiPath.replace(/\\/g,"/"); | ||||
| 	var cbUnicodePathBytes = blob.read_shift(4); | ||||
| 	var usKeyValue = blob.read_shift(2); | ||||
| 	var unicodePath = blob.read_shift(cbUnicodePathBytes>>1, 'utf16le').replace(chr0,""); | ||||
| 	if(blob.read_shift(2) != 0xDEAD) throw new Error("Bad FileMoniker"); | ||||
| 	var sz = blob.read_shift(4); | ||||
| 	if(sz === 0) return ansiPath.replace(/\\/g,"/"); | ||||
| 	var bytes = blob.read_shift(4); | ||||
| 	if(blob.read_shift(2) != 3) throw new Error("Bad FileMoniker"); | ||||
| 	var unicodePath = blob.read_shift(bytes>>1, 'utf16le').replace(chr0,""); | ||||
| 	return unicodePath; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -61,6 +61,14 @@ function parse_Ref8U(blob, length) { | ||||
| 	var colLast = blob.read_shift(2); | ||||
| 	return {s:{c:colFirst, r:rwFirst}, e:{c:colLast,r:rwLast}}; | ||||
| } | ||||
| function write_Ref8U(r/*:Range*/, o) { | ||||
| 	if(!o) o = new_buf(8); | ||||
| 	o.write_shift(2, r.s.r); | ||||
| 	o.write_shift(2, r.e.r); | ||||
| 	o.write_shift(2, r.s.c); | ||||
| 	o.write_shift(2, r.e.c); | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| /* 2.5.211 */ | ||||
| function parse_RefU(blob, length) { | ||||
| @ -165,6 +173,7 @@ function write_BOF(wb/*:Workbook*/, t/*:number*/, o) { | ||||
| 		case 'biff4': h = 0x0004; w = 6; break; | ||||
| 		case 'biff3': h = 0x0003; w = 6; break; | ||||
| 		case 'biff2': h = 0x0002; w = 4; break; | ||||
| 		case 'xla': break; | ||||
| 		default: throw new Error("unsupported BIFF version"); | ||||
| 	} | ||||
| 	var out = new_buf(w); | ||||
| @ -337,6 +346,22 @@ function write_Window1(opts) { | ||||
| 	o.write_shift(2, 0x01f4); | ||||
| 	return o; | ||||
| } | ||||
| /* 2.4.346 TODO */ | ||||
| function parse_Window2(blob, length, opts) { | ||||
| 	if(opts && opts.biff >= 2 && opts.biff < 8) return {}; | ||||
| 	var f = blob.read_shift(2); | ||||
| 	return { RTL: f & 0x40 }; | ||||
| } | ||||
| function write_Window2(view) { | ||||
| 	var o = new_buf(18), f = 0x6b6; | ||||
| 	if(view && view.RTL) f |= 0x40; | ||||
| 	o.write_shift(2, f); | ||||
| 	o.write_shift(4, 0); | ||||
| 	o.write_shift(4, 64); | ||||
| 	o.write_shift(4, 0); | ||||
| 	o.write_shift(4, 0); | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| /* 2.4.122 TODO */ | ||||
| function parse_Font(blob, length, opts) { | ||||
| @ -624,7 +649,6 @@ function parse_ExternSheet(blob, length, opts) { | ||||
| 	var o = [], target = blob.l + length, len = blob.read_shift(opts.biff > 8 ? 4 : 2); | ||||
| 	while(len-- !== 0) o.push(parse_XTI(blob, opts.biff > 8 ? 12 : 6, opts)); | ||||
| 		// [iSupBook, itabFirst, itabLast];
 | ||||
| 	var oo = []; | ||||
| 	return o; | ||||
| } | ||||
| function parse_BIFF5ExternSheet(blob, length, opts) { | ||||
| @ -689,12 +713,18 @@ function parse_Note(blob, length, opts) { | ||||
| } | ||||
| 
 | ||||
| /* 2.4.168 */ | ||||
| function parse_MergeCells(blob, length) { | ||||
| 	var merges = []; | ||||
| function parse_MergeCells(blob, length)/*:Array<Range>*/ { | ||||
| 	var merges/*:Array<Range>*/ = []; | ||||
| 	var cmcs = blob.read_shift(2); | ||||
| 	while (cmcs--) merges.push(parse_Ref8U(blob,length)); | ||||
| 	return merges; | ||||
| } | ||||
| function write_MergeCells(merges/*:Array<Range>*/) { | ||||
| 	var o = new_buf(2 + merges.length * 8); | ||||
| 	o.write_shift(2, merges.length); | ||||
| 	for(var i = 0; i < merges.length; ++i) write_Ref8U(merges[i], o); | ||||
| 	return o; | ||||
| } | ||||
| 
 | ||||
| /* 2.4.181 TODO: parse all the things! */ | ||||
| function parse_Obj(blob, length, opts) { | ||||
| @ -821,8 +851,8 @@ function write_HLinkTooltip(hl) { | ||||
| } | ||||
| 
 | ||||
| /* 2.4.63 */ | ||||
| function parse_Country(blob, length) { | ||||
| 	var o = [], d; | ||||
| function parse_Country(blob, length)/*:[string|number, string|number]*/ { | ||||
| 	var o = [0,0], d; | ||||
| 	d = blob.read_shift(2); o[0] = CountryEnum[d] || d; | ||||
| 	d = blob.read_shift(2); o[1] = CountryEnum[d] || d; | ||||
| 	return o; | ||||
|  | ||||
| @ -86,10 +86,11 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ { | ||||
| 	d.l+=2; | ||||
| 	} | ||||
| 	if(l7) d.l += 36; | ||||
| 	var fields = [], field = {}; | ||||
| /*:: type DBFField = { name:string; len:number; type:string; } */ | ||||
| 	var fields/*:Array<DBFField>*/ = [], field/*:DBFField*/ = ({}/*:any*/); | ||||
| 	var hend = fpos - 10 - (vfp ? 264 : 0), ww = l7 ? 32 : 11; | ||||
| 	while(ft == 0x02 ? d.l < d.length && d[d.l] != 0x0d: d.l < hend) { | ||||
| 		field = {}; | ||||
| 		field = ({}/*:any*/); | ||||
| 		field.name = cptable.utils.decode(current_cp, d.slice(d.l, d.l+ww)).replace(/[\u0000\r\n].*$/g,""); | ||||
| 		d.l += ww; | ||||
| 		field.type = String.fromCharCode(d.read_shift(1)); | ||||
| @ -210,7 +211,7 @@ function sheet_to_dbf(ws/*:Worksheet*/, opts/*:WriteOpts*/) { | ||||
| 			if(headers.indexOf(headers[i] + "_" + j) == -1) { headers[i] += "_" + j; break; } | ||||
| 	} | ||||
| 	var range = safe_decode_range(ws['!ref']); | ||||
| 	var coltypes = []; | ||||
| 	var coltypes/*:Array<string>*/ = []; | ||||
| 	for(i = 0; i <= range.e.c - range.s.c; ++i) { | ||||
| 		var col/*:Array<any>*/ = []; | ||||
| 		for(j=0; j < data.length; ++j) { | ||||
| @ -307,10 +308,10 @@ var SYLK = (function() { | ||||
| 		throw new Error("Unrecognized type " + opts.type); | ||||
| 	} | ||||
| 	function sylk_to_aoa_str(str/*:string*/, opts)/*:[AOA, Worksheet]*/ { | ||||
| 		var records = str.split(/[\n\r]+/), R = -1, C = -1, ri = 0, rj = 0, arr = []; | ||||
| 		var formats = []; | ||||
| 		var next_cell_format = null; | ||||
| 		var sht = {}, rowinfo = [], colinfo = [], cw = []; | ||||
| 		var records = str.split(/[\n\r]+/), R = -1, C = -1, ri = 0, rj = 0, arr/*:AOA*/ = []; | ||||
| 		var formats/*:Array<string>*/ = []; | ||||
| 		var next_cell_format/*:string|null*/ = null; | ||||
| 		var sht = {}, rowinfo/*:Array<RowInfo>*/ = [], colinfo/*:Array<ColInfo>*/ = [], cw/*:Array<string>*/ = []; | ||||
| 		var Mval = 0, j; | ||||
| 		for (; ri !== records.length; ++ri) { | ||||
| 			Mval = 0; | ||||
| @ -484,7 +485,7 @@ var DIF = (function() { | ||||
| 		throw new Error("Unrecognized type " + opts.type); | ||||
| 	} | ||||
| 	function dif_to_aoa_str(str/*:string*/, opts)/*:AOA*/ { | ||||
| 		var records = str.split('\n'), R = -1, C = -1, ri = 0, arr = []; | ||||
| 		var records = str.split('\n'), R = -1, C = -1, ri = 0, arr/*:AOA*/ = []; | ||||
| 		for (; ri !== records.length; ++ri) { | ||||
| 			if (records[ri].trim() === 'BOT') { arr[++R] = []; C = 0; continue; } | ||||
| 			if (R < 0) continue; | ||||
| @ -585,7 +586,7 @@ var ETH = (function() { | ||||
| 	function encode(s/*:string*/)/*:string*/ { return s.replace(/\\/g, "\\b").replace(/:/g, "\\c").replace(/\n/g,"\\n"); } | ||||
| 
 | ||||
| 	function eth_to_aoa(str/*:string*/, opts)/*:AOA*/ { | ||||
| 		var records = str.split('\n'), R = -1, C = -1, ri = 0, arr = []; | ||||
| 		var records = str.split('\n'), R = -1, C = -1, ri = 0, arr/*:AOA*/ = []; | ||||
| 		for (; ri !== records.length; ++ri) { | ||||
| 			var record = records[ri].trim().split(":"); | ||||
| 			if(record[0] !== 'cell') continue; | ||||
| @ -632,7 +633,7 @@ var ETH = (function() { | ||||
| 
 | ||||
| 	function sheet_to_eth_data(ws/*:Worksheet*/)/*:string*/ { | ||||
| 		if(!ws || !ws['!ref']) return ""; | ||||
| 		var o = [], oo = [], cell, coord; | ||||
| 		var o/*:Array<string>*/ = [], oo/*:Array<string>*/ = [], cell, coord = ""; | ||||
| 		var r = decode_range(ws['!ref']); | ||||
| 		var dense = Array.isArray(ws); | ||||
| 		for(var R = r.s.r; R <= r.e.r; ++R) { | ||||
| @ -648,12 +649,12 @@ var ETH = (function() { | ||||
| 						else { oo[2]='vtf'; oo[3]='n'; oo[4]=cell.v; oo[5]=encode(cell.f); } | ||||
| 						break; | ||||
| 					case 'b': | ||||
| 						oo[2] = 'vt'+(cell.f?'f':'c'); oo[3]='nl'; oo[4]=+!!cell.v; | ||||
| 						oo[2] = 'vt'+(cell.f?'f':'c'); oo[3]='nl'; oo[4]=cell.v?"1":"0"; | ||||
| 						oo[5] = encode(cell.f||(cell.v?'TRUE':'FALSE')); | ||||
| 						break; | ||||
| 					case 'd': | ||||
| 						var t = datenum(parseDate(cell.v)); | ||||
| 						oo[2] = 'vtc'; oo[3] = 'nd'; oo[4] = t; | ||||
| 						oo[2] = 'vtc'; oo[3] = 'nd'; oo[4] = ""+t; | ||||
| 						oo[5] = cell.w || SSF.format(cell.z || SSF._table[14], t); | ||||
| 						break; | ||||
| 					case 'e': continue; | ||||
| @ -840,7 +841,7 @@ var PRN = (function() { | ||||
| 		var r = safe_decode_range(ws['!ref']), cell/*:Cell*/; | ||||
| 		var dense = Array.isArray(ws); | ||||
| 		for(var R = r.s.r; R <= r.e.r; ++R) { | ||||
| 			var oo = []; | ||||
| 			var oo/*:Array<string>*/ = []; | ||||
| 			for(var C = r.s.c; C <= r.e.c; ++C) { | ||||
| 				var coord = encode_cell({r:R,c:C}); | ||||
| 				cell = dense ? (ws[R]||[])[C] : ws[coord]; | ||||
|  | ||||
| @ -1,27 +1,3 @@ | ||||
| /* 18.4.1 charset to codepage mapping */ | ||||
| var CS2CP = ({ | ||||
| 	/*::[*/0/*::]*/:    1252, /* ANSI */ | ||||
| 	/*::[*/1/*::]*/:   65001, /* DEFAULT */ | ||||
| 	/*::[*/2/*::]*/:   65001, /* SYMBOL */ | ||||
| 	/*::[*/77/*::]*/:  10000, /* MAC */ | ||||
| 	/*::[*/128/*::]*/:   932, /* SHIFTJIS */ | ||||
| 	/*::[*/129/*::]*/:   949, /* HANGUL */ | ||||
| 	/*::[*/130/*::]*/:  1361, /* JOHAB */ | ||||
| 	/*::[*/134/*::]*/:   936, /* GB2312 */ | ||||
| 	/*::[*/136/*::]*/:   950, /* CHINESEBIG5 */ | ||||
| 	/*::[*/161/*::]*/:  1253, /* GREEK */ | ||||
| 	/*::[*/162/*::]*/:  1254, /* TURKISH */ | ||||
| 	/*::[*/163/*::]*/:  1258, /* VIETNAMESE */ | ||||
| 	/*::[*/177/*::]*/:  1255, /* HEBREW */ | ||||
| 	/*::[*/178/*::]*/:  1256, /* ARABIC */ | ||||
| 	/*::[*/186/*::]*/:  1257, /* BALTIC */ | ||||
| 	/*::[*/204/*::]*/:  1251, /* RUSSIAN */ | ||||
| 	/*::[*/222/*::]*/:   874, /* THAI */ | ||||
| 	/*::[*/238/*::]*/:  1250, /* EASTEUROPE */ | ||||
| 	/*::[*/255/*::]*/:  1252, /* OEM */ | ||||
| 	/*::[*/69/*::]*/:   6969  /* MISC */ | ||||
| }/*:any*/); | ||||
| 
 | ||||
| /* Parse a list of <r> tags */ | ||||
| var parse_rs = (function parse_rs_factory() { | ||||
| 	var tregex = matchtag("t"), rpregex = matchtag("rPr"), rregex = /<(?:\w+:)?r>/g, rend = /<\/(?:\w+:)?r>/, nlregex = /\r\n/g; | ||||
| @ -122,7 +98,7 @@ var parse_rs = (function parse_rs_factory() { | ||||
| 					if(y[0].charCodeAt(1) !== 47) throw 'Unrecognized rich format ' + y[0]; | ||||
| 			} | ||||
| 		} | ||||
| 		var style = []; | ||||
| 		var style/*:Array<string>*/ = []; | ||||
| 
 | ||||
| 		if(font.u) style.push("text-decoration: underline;"); | ||||
| 		if(font.uval) style.push("text-underline-style:" + font.uval + ";"); | ||||
| @ -145,14 +121,14 @@ var parse_rs = (function parse_rs_factory() { | ||||
| 
 | ||||
| 	/* 18.4.4 r CT_RElt */ | ||||
| 	function parse_r(r) { | ||||
| 		var terms = [[],"",[]]; | ||||
| 		var terms/*:[Array<string>, string, Array<string>]*/ = [[],"",[]]; | ||||
| 		/* 18.4.12 t ST_Xstring */ | ||||
| 		var t = r.match(tregex), cp = 65001; | ||||
| 		if(!isval(t)/*:: || !t*/) return ""; | ||||
| 		if(!t) return ""; | ||||
| 		terms[1] = t[1]; | ||||
| 
 | ||||
| 		var rpr = r.match(rpregex); | ||||
| 		if(isval(rpr)/*:: && rpr*/) cp = parse_rpr(rpr[1], terms[0], terms[2]); | ||||
| 		if(rpr) cp = parse_rpr(rpr[1], terms[0], terms[2]); | ||||
| 
 | ||||
| 		return terms[0].join("") + terms[1].replace(nlregex,'<br/>') + terms[2].join(""); | ||||
| 	} | ||||
| @ -196,7 +172,7 @@ function parse_sst_xml(data/*:string*/, opts)/*:SST*/ { | ||||
| 	if(!data) return s; | ||||
| 	/* 18.4.9 sst CT_Sst */ | ||||
| 	var sst = data.match(sstr0); | ||||
| 	if(isval(sst)/*:: && sst*/) { | ||||
| 	if(sst) { | ||||
| 		ss = sst[2].replace(sstr1,"").split(sstr2); | ||||
| 		for(var i = 0; i != ss.length; ++i) { | ||||
| 			var o = parse_si(ss[i].trim(), opts); | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| function _JS2ANSI(str/*:string*/)/*:Array<number>*/ { | ||||
| 	if(typeof cptable !== 'undefined') return cptable.utils.encode(1252, str); | ||||
| 	var o = [], oo = str.split(""); | ||||
| 	if(typeof cptable !== 'undefined') return cptable.utils.encode(current_ansi, str); | ||||
| 	var o/*:Array<number>*/ = [], oo = str.split(""); | ||||
| 	for(var i = 0; i < oo.length; ++i) o[i] = oo[i].charCodeAt(0); | ||||
| 	return o; | ||||
| } | ||||
| @ -31,14 +31,9 @@ function parse_DataSpaceMapEntry(blob) { | ||||
| 	var end = blob.l + len - 4; | ||||
| 	var o = {}; | ||||
| 	var cnt = blob.read_shift(4); | ||||
| 	var comps = []; | ||||
| 	while(cnt-- > 0) { | ||||
| 		/* [MS-OFFCRYPTO] 2.1.6.2 DataSpaceReferenceComponent Structure */ | ||||
| 		var rc = {}; | ||||
| 		rc.t = blob.read_shift(4); | ||||
| 		rc.v = blob.read_shift(0, 'lpp4'); | ||||
| 		comps.push(rc); | ||||
| 	} | ||||
| 	var comps/*:Array<{t:number, v:string}>*/ = []; | ||||
| 	/* [MS-OFFCRYPTO] 2.1.6.2 DataSpaceReferenceComponent Structure */ | ||||
| 	while(cnt-- > 0) comps.push({ t: blob.read_shift(4), v: blob.read_shift(0, 'lpp4') }); | ||||
| 	o.name = blob.read_shift(0, 'lpp4'); | ||||
| 	o.comps = comps; | ||||
| 	if(blob.l != end) throw new Error("Bad DataSpaceMapEntry: " + blob.l + " != " + end); | ||||
| @ -55,8 +50,8 @@ function parse_DataSpaceMap(blob, length) { | ||||
| } | ||||
| 
 | ||||
| /* [MS-OFFCRYPTO] 2.1.7 DataSpaceDefinition */ | ||||
| function parse_DataSpaceDefinition(blob, length) { | ||||
| 	var o = []; | ||||
| function parse_DataSpaceDefinition(blob, length)/*:Array<string>*/ { | ||||
| 	var o/*:Array<string>*/ = []; | ||||
| 	blob.l += 4; // must be 0x8
 | ||||
| 	var cnt = blob.read_shift(4); | ||||
| 	while(cnt-- > 0) o.push(blob.read_shift(0, 'lpp4')); | ||||
|  | ||||
| @ -321,7 +321,7 @@ function parse_cellXfs(t, styles, opts) { | ||||
| } | ||||
| 
 | ||||
| function write_cellXfs(cellXfs)/*:string*/ { | ||||
| 	var o = []; | ||||
| 	var o/*:Array<string>*/ = []; | ||||
| 	o[o.length] = (writextag('cellXfs',null)); | ||||
| 	cellXfs.forEach(function(c) { o[o.length] = (writextag('xf', null, c)); }); | ||||
| 	o[o.length] = ("</cellXfs>"); | ||||
|  | ||||
| @ -206,7 +206,7 @@ function parse_sty_bin(data, themes, opts) { | ||||
| 
 | ||||
| 	styles.CellXf = []; | ||||
| 	styles.Fonts = []; | ||||
| 	var state = []; | ||||
| 	var state/*:Array<string>*/ = []; | ||||
| 	var pass = false; | ||||
| 	recordhopper(data, function hopper_sty(val, R_n, RT) { | ||||
| 		switch(RT) { | ||||
|  | ||||
| @ -1,8 +1,15 @@ | ||||
| /* [MS-XLS] 2.4.326 TODO: payload is a zip file */ | ||||
| function parse_Theme(blob, length, opts) { | ||||
| 	var end = blob.l + length; | ||||
| 	var dwThemeVersion = blob.read_shift(4); | ||||
| 	if(dwThemeVersion === 124226) return; | ||||
| 	blob.l += length-4; | ||||
| 	if(!opts.cellStyles || !jszip) { blob.l = end; return; } | ||||
| 	var data = blob.slice(blob.l); | ||||
| 	blob.l = end; | ||||
| 	var zip; try { zip = new jszip(data); } catch(e) { return; } | ||||
| 	var themeXML = getzipstr(zip, "theme/theme/theme1.xml", true); | ||||
| 	if(!themeXML) return; | ||||
| 	return parse_theme_xml(themeXML, opts); | ||||
| } | ||||
| 
 | ||||
| /* 2.5.49 */ | ||||
| @ -35,7 +42,7 @@ function parse_XFExtGradient(blob, length) { | ||||
| } | ||||
| 
 | ||||
| /* 2.5.108 */ | ||||
| function parse_ExtProp(blob, length) { | ||||
| function parse_ExtProp(blob, length)/*:Array<any>*/ { | ||||
| 	var extType = blob.read_shift(2); | ||||
| 	var cb = blob.read_shift(2); | ||||
| 	var o = [extType]; | ||||
| @ -57,7 +64,7 @@ function parse_XFExt(blob, length) { | ||||
| 	var ixfe = blob.read_shift(2); | ||||
| 	blob.l += 2; | ||||
| 	var cexts = blob.read_shift(2); | ||||
| 	var ext = []; | ||||
| 	var ext/*:AOA*/ = []; | ||||
| 	while(cexts-- > 0) ext.push(parse_ExtProp(blob, end-blob.l)); | ||||
| 	return {ixfe:ixfe, ext:ext}; | ||||
| } | ||||
|  | ||||
| @ -18,9 +18,9 @@ function parse_comments(zip, dirComments, sheets, sheetRels, opts) { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| function insertCommentsIntoSheet(sheetName, sheet, comments) { | ||||
| function insertCommentsIntoSheet(sheetName, sheet, comments/*:Array<RawComment>*/) { | ||||
| 	var dense = Array.isArray(sheet); | ||||
| 	var cell, r; | ||||
| 	var cell/*:Cell*/, r; | ||||
| 	comments.forEach(function(comment) { | ||||
| 		if(dense) { | ||||
| 			r = decode_cell(comment.ref); | ||||
| @ -42,7 +42,7 @@ function insertCommentsIntoSheet(sheetName, sheet, comments) { | ||||
| 		} | ||||
| 
 | ||||
| 		if (!cell.c) cell.c = []; | ||||
| 		var o = ({a: comment.author, t: comment.t, r: comment.r}/*:any*/); | ||||
| 		var o/*:Comment*/ = ({a: comment.author, t: comment.t, r: comment.r}); | ||||
| 		if(comment.h) o.h = comment.h; | ||||
| 		cell.c.push(o); | ||||
| 	}); | ||||
|  | ||||
| @ -1,9 +1,9 @@ | ||||
| /* 18.7 Comments */ | ||||
| function parse_comments_xml(data/*:string*/, opts)/*:Array<Comment>*/ { | ||||
| function parse_comments_xml(data/*:string*/, opts)/*:Array<RawComment>*/ { | ||||
| 	/* 18.7.6 CT_Comments */ | ||||
| 	if(data.match(/<(?:\w+:)?comments *\/>/)) return []; | ||||
| 	var authors = []; | ||||
| 	var commentList = []; | ||||
| 	var authors/*:Array<string>*/ = []; | ||||
| 	var commentList/*:Array<RawComment>*/ = []; | ||||
| 	var authtag = data.match(/<(?:\w+:)?authors>([\s\S]*)<\/(?:\w+:)?authors>/); | ||||
| 	if(authtag && authtag[1]) authtag[1].split(/<\/\w*:?author>/).forEach(function(x) { | ||||
| 		if(x === "" || x.trim() === "") return; | ||||
| @ -16,7 +16,7 @@ function parse_comments_xml(data/*:string*/, opts)/*:Array<Comment>*/ { | ||||
| 		var cm = x.match(/<(?:\w+:)?comment[^>]*>/); | ||||
| 		if(!cm) return; | ||||
| 		var y = parsexmltag(cm[0]); | ||||
| 		var comment/*:Comment*/ = ({ author: y.authorId && authors[y.authorId] || "sheetjsghost", ref: y.ref, guid: y.guid }/*:any*/); | ||||
| 		var comment/*:RawComment*/ = ({ author: y.authorId && authors[y.authorId] || "sheetjsghost", ref: y.ref, guid: y.guid }/*:any*/); | ||||
| 		var cell = decode_cell(y.ref); | ||||
| 		if(opts.sheetRows && opts.sheetRows <= cell.r) return; | ||||
| 		var textMatch = x.match(/<(?:\w+:)?text>([\s\S]*)<\/(?:\w+:)?text>/); | ||||
| @ -34,7 +34,7 @@ var CMNT_XML_ROOT = writextag('comments', null, { 'xmlns': XMLNS.main[0] }); | ||||
| function write_comments_xml(data, opts) { | ||||
| 	var o = [XML_HEADER, CMNT_XML_ROOT]; | ||||
| 
 | ||||
| 	var iauthor = []; | ||||
| 	var iauthor/*:Array<string>*/ = []; | ||||
| 	o.push("<authors>"); | ||||
| 	data.map(function(x) { return x[1]; }).forEach(function(comment) { | ||||
| 		comment.map(function(x) { return escapexml(x.a); }).forEach(function(a) { | ||||
|  | ||||
| @ -24,9 +24,9 @@ var parse_BrtCommentAuthor = parse_XLWideString; | ||||
| function write_BrtCommentAuthor(data) { return write_XLWideString(data.slice(0, 54)); } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.1.7.8 Comments */ | ||||
| function parse_comments_bin(data, opts) { | ||||
| 	var out = []; | ||||
| 	var authors = []; | ||||
| function parse_comments_bin(data, opts)/*:Array<RawComment>*/ { | ||||
| 	var out/*:Array<RawComment>*/ = []; | ||||
| 	var authors/*:Array<string>*/ = []; | ||||
| 	var c = {}; | ||||
| 	var pass = false; | ||||
| 	recordhopper(data, function hopper_cmnt(val, R_n, RT) { | ||||
| @ -65,33 +65,32 @@ function parse_comments_bin(data, opts) { | ||||
| 
 | ||||
| function write_comments_bin(data, opts) { | ||||
| 	var ba = buf_array(); | ||||
| 	var iauthor = []; | ||||
| 	var iauthor/*:Array<string>*/ = []; | ||||
| 	write_record(ba, "BrtBeginComments"); | ||||
| 	{ /* COMMENTAUTHORS */ | ||||
| 		write_record(ba, "BrtBeginCommentAuthors"); | ||||
| 		data.forEach(function(comment) { | ||||
| 			comment[1].forEach(function(c) { | ||||
| 				if(iauthor.indexOf(c.a) > -1) return; | ||||
| 				iauthor.push(c.a.slice(0,54)); | ||||
| 				write_record(ba, "BrtCommentAuthor", write_BrtCommentAuthor(c.a)); | ||||
| 			}); | ||||
| 
 | ||||
| 	write_record(ba, "BrtBeginCommentAuthors"); | ||||
| 	data.forEach(function(comment) { | ||||
| 		comment[1].forEach(function(c) { | ||||
| 			if(iauthor.indexOf(c.a) > -1) return; | ||||
| 			iauthor.push(c.a.slice(0,54)); | ||||
| 			write_record(ba, "BrtCommentAuthor", write_BrtCommentAuthor(c.a)); | ||||
| 		}); | ||||
| 		write_record(ba, "BrtEndCommentAuthors"); | ||||
| 	} | ||||
| 	{ /* COMMENTLIST */ | ||||
| 		write_record(ba, "BrtBeginCommentList"); | ||||
| 		data.forEach(function(comment) { | ||||
| 			comment[1].forEach(function(c) { | ||||
| 				c.iauthor = iauthor.indexOf(c.a); | ||||
| 				var range = {s:decode_cell(comment[0]),e:decode_cell(comment[0])}; | ||||
| 				write_record(ba, "BrtBeginComment", write_BrtBeginComment([range, c])); | ||||
| 				if(c.t && c.t.length > 0) write_record(ba, "BrtCommentText", write_BrtCommentText(c)); | ||||
| 				write_record(ba, "BrtEndComment"); | ||||
| 				delete c.iauthor; | ||||
| 			}); | ||||
| 	}); | ||||
| 	write_record(ba, "BrtEndCommentAuthors"); | ||||
| 
 | ||||
| 	write_record(ba, "BrtBeginCommentList"); | ||||
| 	data.forEach(function(comment) { | ||||
| 		comment[1].forEach(function(c) { | ||||
| 			c.iauthor = iauthor.indexOf(c.a); | ||||
| 			var range = {s:decode_cell(comment[0]),e:decode_cell(comment[0])}; | ||||
| 			write_record(ba, "BrtBeginComment", write_BrtBeginComment([range, c])); | ||||
| 			if(c.t && c.t.length > 0) write_record(ba, "BrtCommentText", write_BrtCommentText(c)); | ||||
| 			write_record(ba, "BrtEndComment"); | ||||
| 			delete c.iauthor; | ||||
| 		}); | ||||
| 		write_record(ba, "BrtEndCommentList"); | ||||
| 	} | ||||
| 	}); | ||||
| 	write_record(ba, "BrtEndCommentList"); | ||||
| 
 | ||||
| 	write_record(ba, "BrtEndComments"); | ||||
| 	return ba.end(); | ||||
| } | ||||
|  | ||||
| @ -16,3 +16,5 @@ function fill_vba_xls(cfb/*:CFBContainer*/, vba/*:CFBContainer*/)/*:void*/ { | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| var VBAFMTS = [ "xlsb", "xlsm", "xlam", "biff8", "xla" ]; | ||||
| 
 | ||||
|  | ||||
| @ -46,3 +46,7 @@ function fuzzyfmla(f/*:string*/)/*:boolean*/ { | ||||
| 	if(f.length == 1) return false; | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| function _xlfn(f/*:string*/)/*:string*/ { | ||||
| 	return f.replace(/_xlfn\./g,""); | ||||
| } | ||||
|  | ||||
| @ -149,10 +149,10 @@ function parse_PtgAttrBaxcel(blob, length) { | ||||
| } | ||||
| 
 | ||||
| /* 2.5.198.34 */ | ||||
| function parse_PtgAttrChoose(blob, length, opts) { | ||||
| function parse_PtgAttrChoose(blob, length, opts)/*:Array<number>*/ { | ||||
| 	blob.l +=2; | ||||
| 	var offset = blob.read_shift(opts && opts.biff == 2 ? 1 : 2); | ||||
| 	var o = []; | ||||
| 	var o/*:Array<number>*/ = []; | ||||
| 	/* offset is 1 less than the number of elements */ | ||||
| 	for(var i = 0; i <= offset; ++i) o.push(blob.read_shift(opts && opts.biff == 2 ? 1 : 2)); | ||||
| 	return o; | ||||
| @ -318,7 +318,7 @@ function parse_SerAr(blob, biff/*:number*/) { | ||||
| /* 2.5.198.61 */ | ||||
| function parse_PtgExtraMem(blob, cce) { | ||||
| 	var count = blob.read_shift(2); | ||||
| 	var out = []; | ||||
| 	var out/*:Array<Range>*/ = []; | ||||
| 	for(var i = 0; i != count; ++i) out.push(parse_Ref8U(blob, 8)); | ||||
| 	return out; | ||||
| } | ||||
| @ -335,7 +335,7 @@ function parse_PtgExtraArray(blob, length, opts) { | ||||
| 	} | ||||
| 	if(opts.biff >= 2 && opts.biff < 8) { --rows; if(--cols == 0) cols = 0x100; } | ||||
| 	// $FlowIgnore
 | ||||
| 	for(var i = 0, o/*:Array<Array<any> >*/=[]; i != rows && (o[i] = []); ++i) | ||||
| 	for(var i = 0, o/*:Array<Array<any>>*/ = []; i != rows && (o[i] = []); ++i) | ||||
| 		for(var j = 0; j != cols; ++j) o[i][j] = parse_SerAr(blob, opts.biff); | ||||
| 	return o; | ||||
| } | ||||
| @ -655,10 +655,10 @@ function parse_Rgce(blob, length, opts) { | ||||
| 	return ptgs; | ||||
| } | ||||
| 
 | ||||
| function stringify_array(f/*:Array<Array<any>>*/)/*:string*/ { | ||||
| 	var o = []; | ||||
| function stringify_array(f/*:Array<Array<string>>*/)/*:string*/ { | ||||
| 	var o/*:Array<string>*/ = []; | ||||
| 	for(var i = 0; i < f.length; ++i) { | ||||
| 		var x = f[i], r = []; | ||||
| 		var x = f[i], r/*:Array<string>*/ = []; | ||||
| 		for(var j = 0; j < x.length; ++j) { | ||||
| 			var y = x[j]; | ||||
| 			if(y) switch(y[0]) { | ||||
| @ -713,10 +713,10 @@ function get_ixti_raw(supbooks, ixti/*:number*/, opts)/*:string*/ { | ||||
| 			return XTI[1] == XTI[2] ? o : o + ":" + supbooks.SheetNames[XTI[2]]; | ||||
| 		case 0x0166: /* 'BrtSupSame' */ | ||||
| 			if(opts.SID != null) return supbooks.SheetNames[opts.SID]; | ||||
| 			return "SH33TJSERR" + supbooks[XTI[0]][0]; | ||||
| 			return "SH33TJSSAME" + supbooks[XTI[0]][0]; | ||||
| 		case 0x0163: /* 'BrtSupBookSrc' */ | ||||
| 			/* falls through */ | ||||
| 		default: return "SH33TJSERR" + supbooks[XTI[0]][0]; | ||||
| 		default: return "SH33TJSSRC" + supbooks[XTI[0]][0]; | ||||
| 	} | ||||
| 	switch(supbooks[XTI[0]][0][0]) { | ||||
| 		case 0x0401: | ||||
| @ -863,7 +863,7 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks, | ||||
| 				/* f[1] = type, 0, nameindex */ | ||||
| 				nameidx = (f[1][2]/*:any*/); | ||||
| 				var lbl = (supbooks.names||[])[nameidx-1] || (supbooks[0]||[])[nameidx]; | ||||
| 				var name = lbl ? lbl.Name : "SH33TJSERR7" + String(nameidx); | ||||
| 				var name = lbl ? lbl.Name : "SH33TJSNAME" + String(nameidx); | ||||
| 				if(name in XLSXFutureFunctions) name = XLSXFutureFunctions[name]; | ||||
| 				stack.push(name); | ||||
| 				break; | ||||
| @ -944,7 +944,7 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks, | ||||
| 				break; | ||||
| 
 | ||||
| 			case 'PtgArray': /* 2.5.198.32 TODO */ | ||||
| 				stack.push("{" + stringify_array(f[1]) + "}"); | ||||
| 				stack.push("{" + stringify_array(/*::(*/f[1]/*:: :any)*/) + "}"); | ||||
| 				break; | ||||
| 
 | ||||
| 			case 'PtgMemArea': /* 2.5.198.70 TODO: confirm this is a non-display */ | ||||
|  | ||||
| @ -1158,6 +1158,7 @@ var XLSXFutureFunctions = { | ||||
| 	"_xlfn.CHISQ.INV.RT": "CHISQ.INV.RT", | ||||
| 	"_xlfn.CHISQ.TEST": "CHISQ.TEST", | ||||
| 	"_xlfn.COMBINA": "COMBINA", | ||||
| 	"_xlfn.CONCAT": "CONCAT", | ||||
| 	"_xlfn.CONFIDENCE.NORM": "CONFIDENCE.NORM", | ||||
| 	"_xlfn.CONFIDENCE.T": "CONFIDENCE.T", | ||||
| 	"_xlfn.COT": "COT", | ||||
| @ -1181,6 +1182,11 @@ var XLSXFutureFunctions = { | ||||
| 	"_xlfn.FILTERXML": "FILTERXML", | ||||
| 	"_xlfn.FLOOR.MATH": "FLOOR.MATH", | ||||
| 	"_xlfn.FLOOR.PRECISE": "FLOOR.PRECISE", | ||||
| 	"_xlfn.FORECAST.ETS": "FORECAST.ETS", | ||||
| 	"_xlfn.FORECAST.ETS.CONFINT": "FORECAST.ETS.CONFINT", | ||||
| 	"_xlfn.FORECAST.ETS.SEASONALITY": "FORECAST.ETS.SEASONALITY", | ||||
| 	"_xlfn.FORECAST.ETS.STAT": "FORECAST.ETS.STAT", | ||||
| 	"_xlfn.FORECAST.LINEAR": "FORECAST.LINEAR", | ||||
| 	"_xlfn.FORMULATEXT": "FORMULATEXT", | ||||
| 	"_xlfn.GAMMA": "GAMMA", | ||||
| 	"_xlfn.GAMMA.DIST": "GAMMA.DIST", | ||||
| @ -1188,8 +1194,8 @@ var XLSXFutureFunctions = { | ||||
| 	"_xlfn.GAMMALN.PRECISE": "GAMMALN.PRECISE", | ||||
| 	"_xlfn.GAUSS": "GAUSS", | ||||
| 	"_xlfn.HYPGEOM.DIST": "HYPGEOM.DIST", | ||||
| 	"_xlfn.IFNA": "IFNA", | ||||
| 	"_xlfn.IFERROR": "IFERROR", | ||||
| 	"_xlfn.IFNA": "IFNA", | ||||
| 	"_xlfn.IMCOSH": "IMCOSH", | ||||
| 	"_xlfn.IMCOT": "IMCOT", | ||||
| 	"_xlfn.IMCSC": "IMCSC", | ||||
| @ -1203,6 +1209,8 @@ var XLSXFutureFunctions = { | ||||
| 	"_xlfn.ISOWEEKNUM": "ISOWEEKNUM", | ||||
| 	"_xlfn.LOGNORM.DIST": "LOGNORM.DIST", | ||||
| 	"_xlfn.LOGNORM.INV": "LOGNORM.INV", | ||||
| 	"_xlfn.MAXIFS": "MAXIFS", | ||||
| 	"_xlfn.MINIFS": "MINIFS", | ||||
| 	"_xlfn.MODE.MULT": "MODE.MULT", | ||||
| 	"_xlfn.MODE.SNGL": "MODE.SNGL", | ||||
| 	"_xlfn.MUNIT": "MUNIT", | ||||
| @ -1242,6 +1250,7 @@ var XLSXFutureFunctions = { | ||||
| 	"_xlfn.T.INV": "T.INV", | ||||
| 	"_xlfn.T.INV.2T": "T.INV.2T", | ||||
| 	"_xlfn.T.TEST": "T.TEST", | ||||
| 	"_xlfn.TEXTJOIN": "TEXTJOIN", | ||||
| 	"_xlfn.UNICHAR": "UNICHAR", | ||||
| 	"_xlfn.UNICODE": "UNICODE", | ||||
| 	"_xlfn.VAR.P": "VAR.P", | ||||
|  | ||||
| @ -37,12 +37,13 @@ function default_margins(margins/*:Margins*/, mode/*:?string*/) { | ||||
| 	if(margins.footer == null) margins.footer = defs[5]; | ||||
| } | ||||
| 
 | ||||
| function get_cell_style(styles, cell, opts) { | ||||
| function get_cell_style(styles/*:Array<any>*/, cell/*:Cell*/, opts) { | ||||
| 	var z = opts.revssf[cell.z != null ? cell.z : "General"]; | ||||
| 	var i = 0x3c, len = styles.length; | ||||
| 	if(z == null && opts.ssf) { | ||||
| 		for(; i < 0x188; ++i) if(opts.ssf[i] == null) { | ||||
| 			SSF.load(cell.z, i); | ||||
| 			// $FlowIgnore
 | ||||
| 			opts.ssf[i] = cell.z; | ||||
| 			opts.revssf[cell.z] = z = i; | ||||
| 			break; | ||||
| @ -60,7 +61,7 @@ function get_cell_style(styles, cell, opts) { | ||||
| 	return len; | ||||
| } | ||||
| 
 | ||||
| function safe_format(p, fmtid/*:number*/, fillid/*:?number*/, opts, themes, styles) { | ||||
| function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, themes, styles) { | ||||
| 	if(p.t === 'z') return; | ||||
| 	if(p.t === 'd' && typeof p.v === 'string') p.v = parseDate(p.v); | ||||
| 	try { | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| function parse_ws_xml_dim(ws, s) { | ||||
| function parse_ws_xml_dim(ws/*:Worksheet*/, s/*:string*/) { | ||||
| 	var d = safe_decode_range(s); | ||||
| 	if(d.s.r<=d.e.r && d.s.c<=d.e.c && d.s.r>=0 && d.s.c>=0) ws["!ref"] = encode_range(d); | ||||
| } | ||||
| @ -10,8 +10,9 @@ var colregex = /<(?:\w:)?col[^>]*[\/]?>/g; | ||||
| var afregex = /<(?:\w:)?autoFilter[^>]*([\/]|>([\s\S]*)<\/(?:\w:)?autoFilter)>/g; | ||||
| var marginregex= /<(?:\w:)?pageMargins[^>]*\/>/g; | ||||
| var sheetprregex = /<(?:\w:)?sheetPr(?:[^>a-z][^>]*)?\/>/; | ||||
| var svsregex = /<(?:\w:)?sheetViews[^>]*(?:[\/]|>([\s\S]*)<\/(?:\w:)?sheetViews)>/; | ||||
| /* 18.3 Worksheets */ | ||||
| function parse_ws_xml(data/*:?string*/, opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/*:Worksheet*/ { | ||||
| function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBProps*/, themes, styles)/*:Worksheet*/ { | ||||
| 	if(!data) return data; | ||||
| 	if(DENSE != null && opts.dense == null) opts.dense = DENSE; | ||||
| 
 | ||||
| @ -30,7 +31,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx, rels, wb/*:WBWBProps*/, theme | ||||
| 	var sheetPr = data1.match(sheetprregex); | ||||
| 	if(sheetPr) parse_ws_xml_sheetpr(sheetPr[0], s, wb, idx); | ||||
| 
 | ||||
| 	/* 18.3.1.35 dimension CT_SheetDimension ? */ | ||||
| 	/* 18.3.1.35 dimension CT_SheetDimension */ | ||||
| 	// $FlowIgnore
 | ||||
| 	var ridx = (data1.match(/<(?:\w*:)?dimension/)||{index:-1}).index; | ||||
| 	if(ridx > 0) { | ||||
| @ -38,8 +39,12 @@ function parse_ws_xml(data/*:?string*/, opts, idx, rels, wb/*:WBWBProps*/, theme | ||||
| 		if(ref) parse_ws_xml_dim(s, ref[1]); | ||||
| 	} | ||||
| 
 | ||||
| 	/* 18.3.1.88 sheetViews CT_SheetViews */ | ||||
| 	var svs = data1.match(svsregex); | ||||
| 	if(svs && svs[1]) parse_ws_xml_sheetviews(svs[1], wb); | ||||
| 
 | ||||
| 	/* 18.3.1.17 cols CT_Cols */ | ||||
| 	var columns = []; | ||||
| 	var columns/*:Array<ColInfo>*/ = []; | ||||
| 	if(opts.cellStyles) { | ||||
| 		/* 18.3.1.13 col CT_Col */ | ||||
| 		var cols = data1.match(colregex); | ||||
| @ -54,10 +59,10 @@ function parse_ws_xml(data/*:?string*/, opts, idx, rels, wb/*:WBWBProps*/, theme | ||||
| 	if(afilter) s['!autofilter'] = parse_ws_xml_autofilter(afilter[0]); | ||||
| 
 | ||||
| 	/* 18.3.1.55 mergeCells CT_MergeCells */ | ||||
| 	var mergecells = []; | ||||
| 	var merges = data2.match(mergecregex); | ||||
| 	if(merges) for(ridx = 0; ridx != merges.length; ++ridx) | ||||
| 		mergecells[ridx] = safe_decode_range(merges[ridx].substr(merges[ridx].indexOf("\"")+1)); | ||||
| 	var merges/*:Array<Range>*/ = []; | ||||
| 	var _merge = data2.match(mergecregex); | ||||
| 	if(_merge) for(ridx = 0; ridx != _merge.length; ++ridx) | ||||
| 		merges[ridx] = safe_decode_range(_merge[ridx].substr(_merge[ridx].indexOf("\"")+1)); | ||||
| 
 | ||||
| 	/* 18.3.1.48 hyperlinks CT_Hyperlinks */ | ||||
| 	var hlink = data2.match(hlinkregex); | ||||
| @ -81,11 +86,11 @@ function parse_ws_xml(data/*:?string*/, opts, idx, rels, wb/*:WBWBProps*/, theme | ||||
| 		} | ||||
| 	} | ||||
| 	if(columns.length > 0) s["!cols"] = columns; | ||||
| 	if(mergecells.length > 0) s["!merges"] = mergecells; | ||||
| 	if(merges.length > 0) s["!merges"] = merges; | ||||
| 	return s; | ||||
| } | ||||
| 
 | ||||
| function write_ws_xml_merges(merges) { | ||||
| function write_ws_xml_merges(merges/*:Array<Range>*/)/*:string*/ { | ||||
| 	if(merges.length === 0) return ""; | ||||
| 	var o = '<mergeCells count="' + merges.length + '">'; | ||||
| 	for(var i = 0; i != merges.length; ++i) o += '<mergeCell ref="' + encode_range(merges[i]) + '"/>'; | ||||
| @ -154,7 +159,7 @@ function parse_ws_xml_margins(margin) { | ||||
| 	}); | ||||
| 	return o; | ||||
| } | ||||
| function write_ws_xml_margins(margin) { | ||||
| function write_ws_xml_margins(margin)/*:string*/ { | ||||
| 	default_margins(margin); | ||||
| 	return writextag('pageMargins', null, margin); | ||||
| } | ||||
| @ -182,7 +187,7 @@ function write_ws_xml_cols(ws, cols)/*:string*/ { | ||||
| 	return o.join(""); | ||||
| } | ||||
| 
 | ||||
| function parse_ws_xml_autofilter(data) { | ||||
| function parse_ws_xml_autofilter(data/*:string*/) { | ||||
| 	var o = { ref: (data.match(/ref="([^"]*)"/)||[])[1]}; | ||||
| 	return o; | ||||
| } | ||||
| @ -192,6 +197,17 @@ function write_ws_xml_autofilter(data)/*:string*/ { | ||||
| 
 | ||||
| /* 18.3.1.88 sheetViews CT_SheetViews */ | ||||
| /* 18.3.1.87 sheetView CT_SheetView */ | ||||
| var sviewregex = /<(?:\w:)?sheetView(?:[^>a-z][^>]*)?\/>/; | ||||
| function parse_ws_xml_sheetviews(data, wb/*:WBWBProps*/) { | ||||
| 	(data.match(sviewregex)||[]).forEach(function(r/*:string*/) { | ||||
| 		var tag = parsexmltag(r); | ||||
| 		if(parsexmlbool(tag.rightToLeft)) { | ||||
| 			if(!wb.Views) wb.Views = [{}]; | ||||
| 			if(!wb.Views[0]) wb.Views[0] = {}; | ||||
| 			wb.Views[0].RTL = true; | ||||
| 		} | ||||
| 	}); | ||||
| } | ||||
| function write_ws_xml_sheetviews(ws, opts, idx, wb)/*:string*/ { | ||||
| 	var sview = {workbookViewId:"0"}; | ||||
| 	// $FlowIgnore
 | ||||
| @ -199,7 +215,7 @@ function write_ws_xml_sheetviews(ws, opts, idx, wb)/*:string*/ { | ||||
| 	return writextag("sheetViews", writextag("sheetView", null, sview), {}); | ||||
| } | ||||
| 
 | ||||
| function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) { | ||||
| function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts, idx, wb)/*:string*/ { | ||||
| 	if(cell.v === undefined && cell.f === undefined || cell.t === 'z') return ""; | ||||
| 	var vv = ""; | ||||
| 	var oldt = cell.t, oldv = cell.v; | ||||
| @ -244,22 +260,22 @@ function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) { | ||||
| 	return writextag('c', v, o); | ||||
| } | ||||
| 
 | ||||
| var parse_ws_xml_data = (function parse_ws_xml_data_factory() { | ||||
| var parse_ws_xml_data = (function() { | ||||
| 	var cellregex = /<(?:\w+:)?c[ >]/, rowregex = /<\/(?:\w+:)?row>/; | ||||
| 	var rregex = /r=["']([^"']*)["']/, isregex = /<(?:\w+:)?is>([\S\s]*?)<\/(?:\w+:)?is>/; | ||||
| 	var refregex = /ref=["']([^"']*)["']/; | ||||
| 	var match_v = matchtag("v"), match_f = matchtag("f"); | ||||
| 
 | ||||
| return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) { | ||||
| 	var ri = 0, x = "", cells = [], cref = [], idx=0, i=0, cc=0, d="", p/*:any*/; | ||||
| return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, themes, styles) { | ||||
| 	var ri = 0, x = "", cells/*:Array<string>*/ = [], cref/*:?Array<string>*/ = [], idx=0, i=0, cc=0, d="", p/*:any*/; | ||||
| 	var tag, tagr = 0, tagc = 0; | ||||
| 	var sstr, ftag; | ||||
| 	var fmtid = 0, fillid = 0; | ||||
| 	var do_format = Array.isArray(styles.CellXf), cf; | ||||
| 	var arrayf = []; | ||||
| 	var arrayf/*:Array<[Range, string]>*/ = []; | ||||
| 	var sharedf = []; | ||||
| 	var dense = Array.isArray(s); | ||||
| 	var rows = [], rowobj = {}, rowrite = false; | ||||
| 	var rows/*:Array<RowInfo>*/ = [], rowobj = {}, rowrite = false; | ||||
| 	for(var marr = sdata.split(rowregex), mt = 0, marrlen = marr.length; mt != marrlen; ++mt) { | ||||
| 		x = marr[mt].trim(); | ||||
| 		var xlen = x.length; | ||||
| @ -307,14 +323,14 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) { | ||||
| 			if(opts.cellFormula) { | ||||
| 				if((cref=d.match(match_f))!= null && /*::cref != null && */cref[1] !== '') { | ||||
| 					/* TODO: match against XLSXFutureFunctions */ | ||||
| 					p.f=unescapexml(utf8read(cref[1])).replace(/_xlfn\./,""); | ||||
| 					p.f=_xlfn(unescapexml(utf8read(cref[1]))); | ||||
| 					if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="array"') > -1) { | ||||
| 						p.F = (d.match(refregex)||[])[1]; | ||||
| 						if(p.F.indexOf(":") > -1) arrayf.push([safe_decode_range(p.F), p.F]); | ||||
| 					} else if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="shared"') > -1) { | ||||
| 						// TODO: parse formula
 | ||||
| 						ftag = parsexmltag(cref[0]); | ||||
| 						sharedf[parseInt(ftag.si, 10)] = [ftag, unescapexml(utf8read(cref[1]))]; | ||||
| 						sharedf[parseInt(ftag.si, 10)] = [ftag, _xlfn(unescapexml(utf8read(cref[1])))]; | ||||
| 					} | ||||
| 				} else if((cref=d.match(/<f[^>]*\/>/))) { | ||||
| 					ftag = parsexmltag(cref[0]); | ||||
| @ -400,7 +416,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) { | ||||
| }; })(); | ||||
| 
 | ||||
| function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/, rels)/*:string*/ { | ||||
| 	var o = [], r = [], range = safe_decode_range(ws['!ref']), cell, ref, rr = "", cols = [], R=0, C=0, rows = ws['!rows']; | ||||
| 	var o/*:Array<string>*/ = [], r/*:Array<string>*/ = [], range = safe_decode_range(ws['!ref']), cell="", ref, rr = "", cols/*:Array<string>*/ = [], R=0, C=0, rows = ws['!rows']; | ||||
| 	var dense = Array.isArray(ws); | ||||
| 	var params = ({r:rr}/*:any*/), row/*:RowInfo*/, height = -1; | ||||
| 	for(C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C); | ||||
|  | ||||
| @ -335,6 +335,11 @@ function write_BrtMargins(margins/*:Margins*/, o) { | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.292 BrtBeginWsView */ | ||||
| function parse_BrtBeginWsView(data, length, opts) { | ||||
| 	var f = data.read_shift(2); | ||||
| 	data.l += 28; | ||||
| 	return { RTL: f & 0x20 }; | ||||
| } | ||||
| function write_BrtBeginWsView(ws, Workbook, o) { | ||||
| 	if(o == null) o = new_buf(30); | ||||
| 	var f = 0x39c; | ||||
| @ -385,7 +390,7 @@ function write_BrtSheetProtection(sp, o) { | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.1.7.61 Worksheet */ | ||||
| function parse_ws_bin(data, _opts, idx, rels, wb, themes, styles)/*:Worksheet*/ { | ||||
| function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/*:Worksheet*/ { | ||||
| 	if(!data) return data; | ||||
| 	var opts = _opts || {}; | ||||
| 	if(!rels) rels = {'!id':{}}; | ||||
| @ -397,24 +402,24 @@ function parse_ws_bin(data, _opts, idx, rels, wb, themes, styles)/*:Worksheet*/ | ||||
| 
 | ||||
| 	var pass = false, end = false; | ||||
| 	var row, p, cf, R, C, addr, sstr, rr, cell/*:Cell*/; | ||||
| 	var mergecells = []; | ||||
| 	var merges/*:Array<Range>*/ = []; | ||||
| 	opts.biff = 12; | ||||
| 	opts['!row'] = 0; | ||||
| 
 | ||||
| 	var ai = 0, af = false; | ||||
| 
 | ||||
| 	var array_formulae = []; | ||||
| 	var shared_formulae = {}; | ||||
| 	var arrayf/*:Array<[Range, string]>*/ = []; | ||||
| 	var sharedf = {}; | ||||
| 	var supbooks = opts.supbooks || ([[]]/*:any*/); | ||||
| 	supbooks.sharedf = shared_formulae; | ||||
| 	supbooks.arrayf = array_formulae; | ||||
| 	supbooks.sharedf = sharedf; | ||||
| 	supbooks.arrayf = arrayf; | ||||
| 	supbooks.SheetNames = wb.SheetNames || wb.Sheets.map(function(x) { return x.name; }); | ||||
| 	if(!opts.supbooks) { | ||||
| 		opts.supbooks = supbooks; | ||||
| 		for(var i = 0; i < wb.Names.length; ++i) supbooks[0][i+1] = wb.Names[i]; | ||||
| 		if(wb.Names) for(var i = 0; i < wb.Names.length; ++i) supbooks[0][i+1] = wb.Names[i]; | ||||
| 	} | ||||
| 
 | ||||
| 	var colinfo = [], rowinfo = []; | ||||
| 	var colinfo/*:Array<ColInfo>*/ = [], rowinfo/*:Array<RowInfo>*/ = []; | ||||
| 	var seencol = false; | ||||
| 
 | ||||
| 	recordhopper(data, function ws_parse(val, R_n, RT) { | ||||
| @ -457,8 +462,8 @@ function parse_ws_bin(data, _opts, idx, rels, wb, themes, styles)/*:Worksheet*/ | ||||
| 				else s[encode_col(C) + rr] = p; | ||||
| 				if(opts.cellFormula) { | ||||
| 					af = false; | ||||
| 					for(ai = 0; ai < array_formulae.length; ++ai) { | ||||
| 						var aii = array_formulae[ai]; | ||||
| 					for(ai = 0; ai < arrayf.length; ++ai) { | ||||
| 						var aii = arrayf[ai]; | ||||
| 						if(row.r >= aii[0].s.r && row.r <= aii[0].e.r) | ||||
| 							if(C >= aii[0].s.c && C <= aii[0].e.c) { | ||||
| 								p.F = encode_range(aii[0]); af = true; | ||||
| @ -488,7 +493,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb, themes, styles)/*:Worksheet*/ | ||||
| 				break; | ||||
| 
 | ||||
| 			case 0x00B0: /* 'BrtMergeCell' */ | ||||
| 				mergecells.push(val); break; | ||||
| 				merges.push(val); break; | ||||
| 
 | ||||
| 			case 0x01EE: /* 'BrtHLink' */ | ||||
| 				var rel = rels['!id'][val.relId]; | ||||
| @ -514,14 +519,14 @@ function parse_ws_bin(data, _opts, idx, rels, wb, themes, styles)/*:Worksheet*/ | ||||
| 
 | ||||
| 			case 0x01AA: /* 'BrtArrFmla' */ | ||||
| 				if(!opts.cellFormula) break; | ||||
| 				array_formulae.push(val); | ||||
| 				arrayf.push(val); | ||||
| 				cell = ((opts.dense ? s[R][C] : s[encode_col(C) + rr])/*:any*/); | ||||
| 				cell.f = stringify_formula(val[1], refguess, {r:row.r, c:C}, supbooks, opts); | ||||
| 				cell.F = encode_range(val[0]); | ||||
| 				break; | ||||
| 			case 0x01AB: /* 'BrtShrFmla' */ | ||||
| 				if(!opts.cellFormula) break; | ||||
| 				shared_formulae[encode_cell(val[0].s)] = val[1]; | ||||
| 				sharedf[encode_cell(val[0].s)] = val[1]; | ||||
| 				cell = (opts.dense ? s[R][C] : s[encode_col(C) + rr]); | ||||
| 				cell.f = stringify_formula(val[1], refguess, {r:row.r, c:C}, supbooks, opts); | ||||
| 				break; | ||||
| @ -549,6 +554,12 @@ function parse_ws_bin(data, _opts, idx, rels, wb, themes, styles)/*:Worksheet*/ | ||||
| 				if(val.name) wb.Sheets[idx].CodeName = val.name; | ||||
| 				break; | ||||
| 
 | ||||
| 			case 0x0089: /* 'BrtBeginWsView' */ | ||||
| 				if(!wb.Views) wb.Views = [{}]; | ||||
| 				if(!wb.Views[0]) wb.Views[0] = {}; | ||||
| 				if(val.RTL) wb.Views[0].RTL = true; | ||||
| 				break; | ||||
| 
 | ||||
| 			case 0x01E5: /* 'BrtWsFmtInfo' */ | ||||
| 			/* case 'BrtUid' */ | ||||
| 			case 0x00AF: /* 'BrtAFilterDateGroupItem' */ | ||||
| @ -635,7 +646,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb, themes, styles)/*:Worksheet*/ | ||||
| 			s["!ref"] = encode_range(tmpref); | ||||
| 		} | ||||
| 	} | ||||
| 	if(mergecells.length > 0) s["!merges"] = mergecells; | ||||
| 	if(merges.length > 0) s["!merges"] = merges; | ||||
| 	if(colinfo.length > 0) s["!cols"] = colinfo; | ||||
| 	if(rowinfo.length > 0) s["!rows"] = rowinfo; | ||||
| 	return s; | ||||
| @ -687,7 +698,7 @@ function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:num | ||||
| } | ||||
| 
 | ||||
| function write_CELLTABLE(ba, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbook*/) { | ||||
| 	var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols = []; | ||||
| 	var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols/*:Array<string>*/ = []; | ||||
| 	write_record(ba, 'BrtBeginSheetData'); | ||||
| 	var dense = Array.isArray(ws); | ||||
| 	var cap = range.e.r; | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| function parse_numCache(data) { | ||||
| 	var col = []; | ||||
| function parse_numCache(data/*:string*/)/*:[Array<number>, string]*/ { | ||||
| 	var col/*:Array<number>*/ = []; | ||||
| 
 | ||||
| 	/* 21.2.2.150 pt CT_NumVal */ | ||||
| 	(data.match(/<c:pt idx="(\d*)">(.*?)<\/c:pt>/mg)||[]).forEach(function(pt) { | ||||
| @ -15,8 +15,8 @@ function parse_numCache(data) { | ||||
| } | ||||
| 
 | ||||
| /* 21.2 DrawingML - Charts */ | ||||
| function parse_chart(data, name/*:string*/, opts, rels, wb, csheet) { | ||||
| 	var cs = ((csheet || {"!type":"chart"})/*:any*/); | ||||
| function parse_chart(data/*:?string*/, name/*:string*/, opts, rels, wb, csheet) { | ||||
| 	var cs/*:Worksheet*/ = ((csheet || {"!type":"chart"})/*:any*/); | ||||
| 	if(!data) return csheet; | ||||
| 	/* 21.2.2.27 chart CT_Chart */ | ||||
| 
 | ||||
|  | ||||
| @ -43,7 +43,7 @@ function parse_cs_bin(data, opts, idx/*:number*/, rels, wb, themes, styles)/*:Wo | ||||
| 	if(!data) return data; | ||||
| 	if(!rels) rels = {'!id':{}}; | ||||
| 	var s = {'!type':"chart", '!chart':null, '!rel':""}; | ||||
| 	var state = []; | ||||
| 	var state/*:Array<string>*/ = []; | ||||
| 	var pass = false; | ||||
| 	recordhopper(data, function cs_parse(val, R_n, RT) { | ||||
| 		switch(RT) { | ||||
|  | ||||
| @ -5,7 +5,6 @@ function parse_wb_xml(data, opts)/*:WorkbookFile*/ { | ||||
| 	var wb = { AppVersion:{}, WBProps:{}, WBView:[], Sheets:[], CalcPr:{}, Names:[], xmlns: "" }; | ||||
| 	var pass = false, xmlns = "xmlns"; | ||||
| 	var dname = {}, dnstart = 0; | ||||
| 	/*(data.match(tagregex)||[]).forEach */ | ||||
| 	data.replace(tagregex, function xml_wb(x, idx) { | ||||
| 		var y/*:any*/ = parsexmltag(x); | ||||
| 		switch(strip_ns(y[0])) { | ||||
|  | ||||
| @ -37,7 +37,7 @@ function parse_sst(data, name/*:string*/, opts)/*:SST*/ { | ||||
| 	return parse_sst_xml((data/*:any*/), opts); | ||||
| } | ||||
| 
 | ||||
| function parse_cmnt(data, name/*:string*/, opts) { | ||||
| function parse_cmnt(data, name/*:string*/, opts)/*:Array<RawComment>*/ { | ||||
| 	if(name.slice(-4)===".bin") return parse_comments_bin((data/*:any*/), opts); | ||||
| 	return parse_comments_xml((data/*:any*/), opts); | ||||
| } | ||||
|  | ||||
| @ -44,7 +44,7 @@ function xlml_format(format, value)/*:string*/ { | ||||
| 	return SSF.format(fmt, value); | ||||
| } | ||||
| 
 | ||||
| function xlml_set_custprop(Custprops, Rn, cp, val/*:string*/) { | ||||
| function xlml_set_custprop(Custprops, key, cp, val/*:string*/) { | ||||
| 	var oval/*:any*/ = val; | ||||
| 	switch((cp[0].match(/dt:dt="([\w.]+)"/)||["",""])[1]) { | ||||
| 		case "boolean": oval = parsexmlbool(val); break; | ||||
| @ -54,7 +54,7 @@ function xlml_set_custprop(Custprops, Rn, cp, val/*:string*/) { | ||||
| 		case "i8": case "string": case "fixed": case "uuid": case "bin.base64": break; | ||||
| 		default: throw new Error("bad custprop:" + cp[0]); | ||||
| 	} | ||||
| 	Custprops[unescapexml(Rn[3])] = oval; | ||||
| 	Custprops[unescapexml(key)] = oval; | ||||
| } | ||||
| 
 | ||||
| function safe_format_xlml(cell/*:Cell*/, nf, o) { | ||||
| @ -174,7 +174,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ { | ||||
| 	var opts = _opts || {}; | ||||
| 	make_ssf(SSF); | ||||
| 	var str = debom(xlml_normalize(d)); | ||||
| 	if(opts.type == 'binary' || opts.type == 'base64') { | ||||
| 	if(opts.type == 'binary' || opts.type == 'array' || opts.type == 'base64') { | ||||
| 		if(typeof cptable !== 'undefined') str = cptable.utils.decode(65001, char_codes(str)); | ||||
| 		else str = utf8read(str); | ||||
| 	} | ||||
| @ -184,19 +184,19 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ { | ||||
| 	var Rn; | ||||
| 	var state = [], tmp; | ||||
| 	if(DENSE != null && opts.dense == null) opts.dense = DENSE; | ||||
| 	var sheets = {}, sheetnames = [], cursheet/*:Worksheet*/ = (opts.dense ? [] : {}), sheetname = ""; | ||||
| 	var sheets = {}, sheetnames/*:Array<string>*/ = [], cursheet/*:Worksheet*/ = (opts.dense ? [] : {}), sheetname = ""; | ||||
| 	var table = {}, cell = ({}/*:any*/), row = {}; | ||||
| 	var dtag = xlml_parsexmltag('<Data ss:Type="String">'), didx = 0; | ||||
| 	var c = 0, r = 0; | ||||
| 	var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} }; | ||||
| 	var refguess/*:Range*/ = {s: {r:2000000, c:2000000}, e: {r:0, c:0} }; | ||||
| 	var styles = {}, stag = {}; | ||||
| 	var ss = "", fidx = 0; | ||||
| 	var mergecells = []; | ||||
| 	var Props = {}, Custprops = {}, pidx = 0, cp = {}; | ||||
| 	var comments = [], comment = {}; | ||||
| 	var merges/*:Array<Range>*/ = []; | ||||
| 	var Props = {}, Custprops = {}, pidx = 0, cp = []; | ||||
| 	var comments/*:Array<Comment>*/ = [], comment/*:Comment*/ = ({}/*:any*/); | ||||
| 	var cstys = [], csty, seencol = false; | ||||
| 	var arrayf = []; | ||||
| 	var rowinfo = [], rowobj = {}, cc = 0, rr = 0; | ||||
| 	var arrayf/*:Array<[Range, string]>*/ = []; | ||||
| 	var rowinfo/*:Array<RowInfo>*/ = [], rowobj = {}, cc = 0, rr = 0; | ||||
| 	var Workbook/*:WBWBProps*/ = ({ Sheets:[], WBProps:{date1904:false} }/*:any*/), wsprops = {}; | ||||
| 	xlmlregex.lastIndex = 0; | ||||
| 	str = str.replace(/<!--([\s\S]*?)-->/mg,""); | ||||
| @ -223,7 +223,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ { | ||||
| 				if(cell.MergeAcross || cell.MergeDown) { | ||||
| 					cc = c + (parseInt(cell.MergeAcross,10)|0); | ||||
| 					rr = r + (parseInt(cell.MergeDown,10)|0); | ||||
| 					mergecells.push({s:{c:c,r:r},e:{c:cc,r:rr}}); | ||||
| 					merges.push({s:{c:c,r:r},e:{c:cc,r:rr}}); | ||||
| 				} | ||||
| 				if(!opts.sheetStubs) { if(cell.MergeAcross) c = cc + 1; else ++c; } | ||||
| 				else if(cell.MergeAcross || cell.MergeDown) { | ||||
| @ -275,7 +275,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ { | ||||
| 				if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|")); | ||||
| 				sheetnames.push(sheetname); | ||||
| 				if(refguess.s.r <= refguess.e.r && refguess.s.c <= refguess.e.c) cursheet["!ref"] = encode_range(refguess); | ||||
| 				if(mergecells.length) cursheet["!merges"] = mergecells; | ||||
| 				if(merges.length) cursheet["!merges"] = merges; | ||||
| 				if(cstys.length > 0) cursheet["!cols"] = cstys; | ||||
| 				if(rowinfo.length > 0) cursheet["!rows"] = rowinfo; | ||||
| 				sheets[sheetname] = cursheet; | ||||
| @ -286,7 +286,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ { | ||||
| 				tmp = xlml_parsexmltag(Rn[0]); | ||||
| 				sheetname = unescapexml(tmp.Name); | ||||
| 				cursheet = (opts.dense ? [] : {}); | ||||
| 				mergecells = []; | ||||
| 				merges = []; | ||||
| 				arrayf = []; | ||||
| 				rowinfo = []; | ||||
| 				wsprops = {name:sheetname, Hidden:0}; | ||||
| @ -402,7 +402,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ { | ||||
| 			} else { | ||||
| 				state.push([Rn[3], false]); | ||||
| 				tmp = xlml_parsexmltag(Rn[0]); | ||||
| 				comment = {a:tmp.Author}; | ||||
| 				comment = ({a:tmp.Author}/*:any*/); | ||||
| 			} | ||||
| 			break; | ||||
| 
 | ||||
| @ -565,6 +565,12 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ { | ||||
| 						if(pagemargins.Right) cursheet['!margins'].right = pagemargins.Right; | ||||
| 						if(pagemargins.Bottom) cursheet['!margins'].bottom = pagemargins.Bottom; | ||||
| 						break; | ||||
| 					case 'DisplayRightToLeft': | ||||
| 						if(!Workbook.Views) Workbook.Views = []; | ||||
| 						if(!Workbook.Views[0]) Workbook.Views[0] = {}; | ||||
| 						Workbook.Views[0].RTL = true; | ||||
| 						break; | ||||
| 
 | ||||
| 					case 'Unsynced': break; | ||||
| 					case 'Print': break; | ||||
| 					case 'Panes': break; | ||||
| @ -806,7 +812,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ { | ||||
| 			if(!state[state.length-1][1]) throw 'Unrecognized tag: ' + Rn[3] + "|" + state.join("|"); | ||||
| 			if(state[state.length-1][0]==='CustomDocumentProperties') { | ||||
| 				if(Rn[0].slice(-2) === "/>") break; | ||||
| 				else if(Rn[1]==="/") xlml_set_custprop(Custprops, Rn, cp, str.slice(pidx, Rn.index)); | ||||
| 				else if(Rn[1]==="/") xlml_set_custprop(Custprops, Rn[3], cp, str.slice(pidx, Rn.index)); | ||||
| 				else { cp = Rn; pidx = Rn.index + Rn[0].length; } | ||||
| 				break; | ||||
| 			} | ||||
| @ -822,11 +828,6 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ { | ||||
| 	return out; | ||||
| } | ||||
| 
 | ||||
| function arr2str(data/*:any*/)/*:string*/ { | ||||
| 	if(Array.isArray(data)) return data.map(_chr).join(""); | ||||
| 	var o = []; for(var i = 0; i < data.length; ++i) o[i] = _chr(data[i]); return o.join(""); | ||||
| } | ||||
| 
 | ||||
| function parse_xlml(data/*:RawBytes|string*/, opts)/*:Workbook*/ { | ||||
| 	fix_read_opts(opts=opts||{}); | ||||
| 	switch(opts.type||"base64") { | ||||
| @ -838,8 +839,8 @@ function parse_xlml(data/*:RawBytes|string*/, opts)/*:Workbook*/ { | ||||
| } | ||||
| 
 | ||||
| /* TODO */ | ||||
| function write_props_xlml(wb, opts) { | ||||
| 	var o = []; | ||||
| function write_props_xlml(wb/*:Workbook*/, opts)/*:string*/ { | ||||
| 	var o/*:Array<string>*/ = []; | ||||
| 	/* DocumentProperties */ | ||||
| 	if(wb.Props) o.push(xlml_write_docprops(wb.Props, opts)); | ||||
| 	/* CustomDocumentProperties */ | ||||
| @ -847,7 +848,7 @@ function write_props_xlml(wb, opts) { | ||||
| 	return o.join(""); | ||||
| } | ||||
| /* TODO */ | ||||
| function write_wb_xlml(wb, opts) { | ||||
| function write_wb_xlml(wb, opts)/*:string*/ { | ||||
| 	/* OfficeDocumentSettings */ | ||||
| 	/* ExcelWorkbook */ | ||||
| 	return ""; | ||||
| @ -855,12 +856,18 @@ function write_wb_xlml(wb, opts) { | ||||
| /* TODO */ | ||||
| function write_sty_xlml(wb, opts)/*:string*/ { | ||||
| 	/* Styles */ | ||||
| 	return ""; | ||||
| 	var styles/*:Array<string>*/ = ['<Style ss:ID="Default" ss:Name="Normal"><NumberFormat/></Style>']; | ||||
| 	opts.cellXfs.forEach(function(xf, id) { | ||||
| 		var payload/*:Array<string>*/ = []; | ||||
| 		payload.push(writextag('NumberFormat', null, {"ss:Format": escapexml(SSF._table[xf.numFmtId])})); | ||||
| 		styles.push(writextag('Style', payload.join(""), {"ss:ID": "s" + (21+id)})); | ||||
| 	}); | ||||
| 	return writextag("Styles", styles.join("")); | ||||
| } | ||||
| /* WorksheetOptions */ | ||||
| function write_ws_xlml_wsopts(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/)/*:string*/ { | ||||
| 	if(!ws) return ""; | ||||
| 	var o = []; | ||||
| 	var o/*:Array<string>*/ = []; | ||||
| 	/* NOTE: spec technically allows any order, but stick with implied order */ | ||||
| 
 | ||||
| 	/* FitToPage */ | ||||
| @ -913,7 +920,10 @@ function write_ws_xlml_wsopts(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workb | ||||
| 	} | ||||
| 
 | ||||
| 	/* LeftColumnVisible */ | ||||
| 	/* DisplayRightToLeft */ | ||||
| 
 | ||||
| 	// $FlowIgnore
 | ||||
| 	if(((((wb||{}).Workbook||{}).Views||[])[0]||{}).RTL) o.push("<DisplayRightToLeft/>"); | ||||
| 
 | ||||
| 	/* GridlineColorIndex */ | ||||
| 	/* DisplayFormulas */ | ||||
| 	/* DoNotDisplayGridlines */ | ||||
| @ -1001,9 +1011,12 @@ function write_ws_xlml_cell(cell, ref/*:string*/, ws, opts, idx/*:number*/, wb, | ||||
| 		case 'n': t = 'Number'; p = String(cell.v); break; | ||||
| 		case 'b': t = 'Boolean'; p = (cell.v ? "1" : "0"); break; | ||||
| 		case 'e': t = 'Error'; p = BErr[cell.v]; break; | ||||
| 		case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); break; | ||||
| 		case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); if(cell.z == null) cell.z = cell.z || SSF._table[14]; break; | ||||
| 		case 's': t = 'String'; p = escapexml(cell.v||""); break; | ||||
| 	} | ||||
| 	/* TODO: cell style */ | ||||
| 	var os = get_cell_style(opts.cellXfs, cell, opts); | ||||
| 	attr["ss:StyleID"] = "s" + (21+os); | ||||
| 	var _v = (cell.v != null ? p : ""); | ||||
| 	var m = '<Data ss:Type="' + t + '">' + _v + '</Data>'; | ||||
| 
 | ||||
| @ -1023,9 +1036,9 @@ function write_ws_xlml_row(R/*:number*/, row)/*:string*/ { | ||||
| /* TODO */ | ||||
| function write_ws_xlml_table(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/)/*:string*/ { | ||||
| 	if(!ws['!ref']) return ""; | ||||
| 	var range = safe_decode_range(ws['!ref']); | ||||
| 	var marr = ws['!merges'] || [], mi = 0; | ||||
| 	var o = []; | ||||
| 	var range/*:Range*/ = safe_decode_range(ws['!ref']); | ||||
| 	var marr/*:Array<Range>*/ = ws['!merges'] || [], mi = 0; | ||||
| 	var o/*:Array<string>*/ = []; | ||||
| 	if(ws['!cols']) ws['!cols'].forEach(function(n, i) { | ||||
| 		process_col(n); | ||||
| 		var w = !!n.width; | ||||
| @ -1059,7 +1072,7 @@ function write_ws_xlml_table(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbo | ||||
| 	return o.join(""); | ||||
| } | ||||
| function write_ws_xlml(idx/*:number*/, opts, wb/*:Workbook*/)/*:string*/ { | ||||
| 	var o = []; | ||||
| 	var o/*:Array<string>*/ = []; | ||||
| 	var s = wb.SheetNames[idx]; | ||||
| 	var ws = wb.Sheets[s]; | ||||
| 
 | ||||
| @ -1073,12 +1086,23 @@ function write_ws_xlml(idx/*:number*/, opts, wb/*:Workbook*/)/*:string*/ { | ||||
| 	return o.join(""); | ||||
| } | ||||
| function write_xlml(wb, opts)/*:string*/ { | ||||
| 	var d = []; | ||||
| 	if(!opts) opts = {}; | ||||
| 	if(!wb.SSF) wb.SSF = SSF.get_table(); | ||||
| 	if(wb.SSF) { | ||||
| 		make_ssf(SSF); SSF.load_table(wb.SSF); | ||||
| 		// $FlowIgnore
 | ||||
| 		opts.revssf = evert_num(wb.SSF); opts.revssf[wb.SSF[65535]] = 0; | ||||
| 		opts.ssf = wb.SSF; | ||||
| 		opts.cellXfs = []; | ||||
| 		get_cell_style(opts.cellXfs, {}, {revssf:{"General":0}}); | ||||
| 	} | ||||
| 	var d/*:Array<string>*/ = []; | ||||
| 	d.push(write_props_xlml(wb, opts)); | ||||
| 	d.push(write_wb_xlml(wb, opts)); | ||||
| 	d.push(write_sty_xlml(wb, opts)); | ||||
| 	d.push(""); | ||||
| 	for(var i = 0; i < wb.SheetNames.length; ++i) | ||||
| 		d.push(writextag("Worksheet", write_ws_xlml(i, opts, wb), {"ss:Name":escapexml(wb.SheetNames[i])})); | ||||
| 	d[2] = write_sty_xlml(wb, opts); | ||||
| 	return XML_HEADER + writextag("Workbook", d.join(""), { | ||||
| 		'xmlns':      XLMLNS.ss, | ||||
| 		'xmlns:o':    XLMLNS.o, | ||||
|  | ||||
							
								
								
									
										121
									
								
								bits/76_xls.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										121
									
								
								bits/76_xls.js
									
									
									
									
									
								
							| @ -5,25 +5,25 @@ function parse_compobj(obj/*:CFBEntry*/) { | ||||
| 	/*:: if(o == null) return; */ | ||||
| 
 | ||||
| 	/* [MS-OLEDS] 2.3.7 CompObjHeader -- All fields MUST be ignored */ | ||||
| 	var l = 28, m; | ||||
| 	m = __lpstr(o, l); | ||||
| 	l += 4 + __readUInt32LE(o,l); | ||||
| 	v.UserType = m; | ||||
| 	o.l = 28; | ||||
| 
 | ||||
| 	/* [MS-OLEDS] 2.3.1 ClipboardFormatOrAnsiString */ | ||||
| 	m = __readUInt32LE(o,l); l+= 4; | ||||
| 	switch(m) { | ||||
| 		case 0x00000000: break; | ||||
| 		case 0xffffffff: case 0xfffffffe: l+=4; break; | ||||
| 		default: | ||||
| 			if(m > 0x190) throw new Error("Unsupported Clipboard: " + m.toString(16)); | ||||
| 			l += m; | ||||
| 	} | ||||
| 	v.AnsiUserType = o.read_shift(0, "lpstr-ansi"); | ||||
| 	v.AnsiClipboardFormat = parse_ClipboardFormatOrAnsiString(o); | ||||
| 
 | ||||
| 	m = __lpstr(o, l); l += m.length === 0 ? 0 : 5 + m.length; v.Reserved1 = m; | ||||
| 	if(o.length - o.l <= 4) return v; | ||||
| 
 | ||||
| 	if((m = __readUInt32LE(o,l)) !== 0x71b2e9f4) return v; | ||||
| 	throw new Error("Unsupported Unicode Extension"); | ||||
| 	var m/*:number*/ = o.read_shift(4); | ||||
| 	if(m == 0 || m > 40) return v; | ||||
| 	o.l-=4; v.Reserved1 = o.read_shift(0, "lpstr-ansi"); | ||||
| 
 | ||||
| 	if(o.length - o.l <= 4) return v; | ||||
| 	m = o.read_shift(4); | ||||
| 	if(m !== 0x71b239f4) return v; | ||||
| 	v.UnicodeClipboardFormat = parse_ClipboardFormatOrUnicodeString(o); | ||||
| 
 | ||||
| 	m = o.read_shift(4); | ||||
| 	if(m == 0 || m > 40) return v; | ||||
| 	o.l-=4; v.Reserved2 = o.read_shift(0, "lpwstr"); | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| @ -99,21 +99,20 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 	if(DENSE != null && options.dense == null) options.dense = DENSE; | ||||
| 	var out/*:Worksheet*/ = ((options.dense ? [] : {})/*:any*/); | ||||
| 	var Directory = {}; | ||||
| 	var found_sheet = false; | ||||
| 	var range/*:Range*/ = ({}/*:any*/); | ||||
| 	var last_formula = null; | ||||
| 	var sst = []; | ||||
| 	var sst/*:SST*/ = ([]/*:any*/); | ||||
| 	var cur_sheet = ""; | ||||
| 	var Preamble = {}; | ||||
| 	var lastcell, last_cell = "", cc, cmnt, rng, rngC, rngR; | ||||
| 	var lastcell, last_cell = "", cc, cmnt, rngC, rngR; | ||||
| 	var shared_formulae = {}; | ||||
| 	var array_formulae = []; /* TODO: something more clever */ | ||||
| 	var arrayf/*:Array<[Range, string]>*/ = []; | ||||
| 	var temp_val/*:Cell*/; | ||||
| 	var country; | ||||
| 	var cell_valid = true; | ||||
| 	var XFs = []; /* XF records */ | ||||
| 	var palette = []; | ||||
| 	var Workbook/*:WBWBProps*/ = ({ Sheets:[], WBProps:{date1904:false} }/*:any*/), wsprops = {}; | ||||
| 	var Workbook/*:WBWBProps*/ = ({ Sheets:[], WBProps:{date1904:false}, Views:[{}] }/*:any*/), wsprops = {}; | ||||
| 	var get_rgb = function getrgb(icv) { | ||||
| 		if(icv < 8) return XLSIcv[icv]; | ||||
| 		if(icv < 64) return palette[icv-8] || XLSIcv[icv]; | ||||
| @ -144,15 +143,15 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 			if(cell.c + 1 > range.e.c) range.e.c = cell.c + 1; | ||||
| 		} | ||||
| 		if(options.cellFormula && line.f) { | ||||
| 			for(var afi = 0; afi < array_formulae.length; ++afi) { | ||||
| 				if(array_formulae[afi][0].s.c > cell.c) continue; | ||||
| 				if(array_formulae[afi][0].s.r > cell.r) continue; | ||||
| 				if(array_formulae[afi][0].e.c < cell.c) continue; | ||||
| 				if(array_formulae[afi][0].e.r < cell.r) continue; | ||||
| 				line.F = encode_range(array_formulae[afi][0]); | ||||
| 				if(array_formulae[afi][0].s.c != cell.c) delete line.f; | ||||
| 				if(array_formulae[afi][0].s.r != cell.r) delete line.f; | ||||
| 				if(line.f) line.f = "" + stringify_formula(array_formulae[afi][1], range, cell, supbooks, opts); | ||||
| 			for(var afi = 0; afi < arrayf.length; ++afi) { | ||||
| 				if(arrayf[afi][0].s.c > cell.c) continue; | ||||
| 				if(arrayf[afi][0].s.r > cell.r) continue; | ||||
| 				if(arrayf[afi][0].e.c < cell.c) continue; | ||||
| 				if(arrayf[afi][0].e.r < cell.r) continue; | ||||
| 				line.F = encode_range(arrayf[afi][0]); | ||||
| 				if(arrayf[afi][0].s.c != cell.c) delete line.f; | ||||
| 				if(arrayf[afi][0].s.r != cell.r) delete line.f; | ||||
| 				if(line.f) line.f = "" + stringify_formula(arrayf[afi][1], range, cell, supbooks, opts); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| @ -169,7 +168,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 		sbcch: 0, // cch in the preceding SupBook
 | ||||
| 		snames: [], // sheetnames
 | ||||
| 		sharedf: shared_formulae, // shared formulae by address
 | ||||
| 		arrayf: array_formulae, // array formulae array
 | ||||
| 		arrayf: arrayf, // array formulae array
 | ||||
| 		rrtabid: [], // RRTabId
 | ||||
| 		lastuser: "", // Last User from WriteAccess
 | ||||
| 		biff: 8, // BIFF version
 | ||||
| @ -179,9 +178,10 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 		WTF: !!options && !!options.wtf | ||||
| 	}/*:any*/); | ||||
| 	if(options.password) opts.password = options.password; | ||||
| 	var mergecells = []; | ||||
| 	var themes; | ||||
| 	var merges/*:Array<Range>*/ = []; | ||||
| 	var objects = []; | ||||
| 	var colinfo = [], rowinfo = []; | ||||
| 	var colinfo/*:Array<ColInfo>*/ = [], rowinfo/*:Array<RowInfo>*/ = []; | ||||
| 	var defwidth = 0, defheight = 0; // twips / MDW respectively
 | ||||
| 	var seencol = false; | ||||
| 	var supbooks = ([]/*:any*/); // 1-indexed, will hold extern names
 | ||||
| @ -192,8 +192,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 	supbooks.XTI = []; | ||||
| 	var last_Rn = ''; | ||||
| 	var file_depth = 0; /* TODO: make a real stack */ | ||||
| 	var BIFF2Fmt = 0; | ||||
| 	var BIFF2FmtTable/*:Array<string>*/ = []; | ||||
| 	var BIFF2Fmt = 0, BIFF2FmtTable/*:Array<string>*/ = []; | ||||
| 	var FilterDatabases = []; /* TODO: sort out supbooks and process elsewhere */ | ||||
| 	var last_lbl/*:?DefinedName*/; | ||||
| 
 | ||||
| @ -291,7 +290,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 					}/*:DefinedName*/); | ||||
| 					if(val.itab > 0) last_lbl.Sheet = val.itab - 1; | ||||
| 					supbooks.names.push(last_lbl); | ||||
| 					if(!supbooks[0]) supbooks[0] = []; | ||||
| 					if(!supbooks[0]) { supbooks[0] = []; supbooks[0].XTI = []; } | ||||
| 					supbooks[supbooks.length-1].push(val); | ||||
| 					if(val.Name == "_xlnm._FilterDatabase" && val.itab > 0) | ||||
| 						if(val.rgce && val.rgce[0] && val.rgce[0][0] && val.rgce[0][0][0] == 'PtgArea3d') | ||||
| @ -323,7 +322,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 							out["!ref"] = encode_range(range); | ||||
| 							range.e.r++; range.e.c++; | ||||
| 						} | ||||
| 						if(mergecells.length > 0) out["!merges"] = mergecells; | ||||
| 						if(merges.length > 0) out["!merges"] = merges; | ||||
| 						if(objects.length > 0) out["!objects"] = objects; | ||||
| 						if(colinfo.length > 0) out["!cols"] = colinfo; | ||||
| 						if(rowinfo.length > 0) out["!rows"] = rowinfo; | ||||
| @ -333,16 +332,16 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 					out = ((options.dense ? [] : {})/*:any*/); | ||||
| 				} break; | ||||
| 				case 'BOF': { | ||||
| 					if(opts.biff === 8) switch(RecordType) { | ||||
| 						case 0x0009: opts.biff = 2; break; | ||||
| 						case 0x0209: opts.biff = 3; break; | ||||
| 						case 0x0409: opts.biff = 4; break; | ||||
| 						default: switch(val.BIFFVer) { | ||||
| 						case 0x0500: opts.biff = 5; break; | ||||
| 						case 0x0600: opts.biff = 8; break; | ||||
| 						case 0x0002: opts.biff = 2; break; | ||||
| 						case 0x0007: opts.biff = 2; break; | ||||
| 					}} | ||||
| 					if(opts.biff === 8) opts.biff = { | ||||
| 						/*::[*/0x0009/*::]*/:2, | ||||
| 						/*::[*/0x0209/*::]*/:3, | ||||
| 						/*::[*/0x0409/*::]*/:4 | ||||
| 					}[RecordType] || { | ||||
| 						/*::[*/0x0500/*::]*/:5, | ||||
| 						/*::[*/0x0600/*::]*/:8, | ||||
| 						/*::[*/0x0002/*::]*/:2, | ||||
| 						/*::[*/0x0007/*::]*/:2 | ||||
| 					}[val.BIFFVer] || 8; | ||||
| 					if(file_depth++) break; | ||||
| 					cell_valid = true; | ||||
| 					out = ((options.dense ? [] : {})/*:any*/); | ||||
| @ -359,9 +358,9 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 					else cur_sheet = (Directory[s] || {name:""}).name; | ||||
| 					if(val.dt == 0x20) out["!type"] = "chart"; | ||||
| 					if(val.dt == 0x40) out["!type"] = "macro"; | ||||
| 					mergecells = []; | ||||
| 					merges = []; | ||||
| 					objects = []; | ||||
| 					array_formulae = []; opts.arrayf = array_formulae; | ||||
| 					opts.arrayf = arrayf = []; | ||||
| 					colinfo = []; rowinfo = []; | ||||
| 					defwidth = defheight = 0; | ||||
| 					seencol = false; | ||||
| @ -429,7 +428,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 					} else throw new Error("String record expects Formula"); | ||||
| 				} break; | ||||
| 				case 'Array': { | ||||
| 					array_formulae.push(val); | ||||
| 					arrayf.push(val); | ||||
| 					var _arraystart = encode_cell(val[0].s); | ||||
| 					cc = options.dense ? (out[val[0].s.r]||[])[val[0].s.c] : out[_arraystart]; | ||||
| 					if(options.cellFormula && cc) { | ||||
| @ -501,7 +500,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 					if(b2idx >= 163) SSF.load(val, BIFF2Fmt + 163); | ||||
| 				} break; | ||||
| 
 | ||||
| 				case 'MergeCells': mergecells = mergecells.concat(val); break; | ||||
| 				case 'MergeCells': merges = merges.concat(val); break; | ||||
| 
 | ||||
| 				case 'Obj': objects[val.cmo[0]] = opts.lastobj = val; break; | ||||
| 				case 'TxO': opts.lastobj.TxO = val; break; | ||||
| @ -572,6 +571,11 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 					out['!margins'].footer = val.footer; | ||||
| 					break; | ||||
| 
 | ||||
| 				case 'Window2': // TODO
 | ||||
| 					// $FlowIgnore
 | ||||
| 					if(val.RTL) Workbook.Views[0].RTL = true; | ||||
| 					break; | ||||
| 
 | ||||
| 				case 'Header': break; // TODO
 | ||||
| 				case 'Footer': break; // TODO
 | ||||
| 				case 'HCenter': break; // TODO
 | ||||
| @ -605,8 +609,8 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 				case 'XFCRC': break; // TODO
 | ||||
| 				case 'Style': break; // TODO
 | ||||
| 				case 'StyleExt': break; // TODO
 | ||||
| 				case 'Palette': palette = val; break; // TODO
 | ||||
| 				case 'Theme': break; // TODO
 | ||||
| 				case 'Palette': palette = val; break; | ||||
| 				case 'Theme': themes = val; break; | ||||
| 				/* Protection */ | ||||
| 				case 'ScenarioProtect': break; | ||||
| 				case 'ObjProtect': break; | ||||
| @ -710,7 +714,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 				case 'InterfaceHdr': case 'Mms': case 'InterfaceEnd': case 'DSF': break; | ||||
| 				case 'BuiltInFnGroupCount': /* 2.4.30 0x0E or 0x10 but excel 2011 generates 0x11? */ break; | ||||
| 				/* View Stuff */ | ||||
| 				case 'Window1': case 'Window2': case 'HideObj': case 'GridSet': case 'Guts': | ||||
| 				case 'Window1': case 'HideObj': case 'GridSet': case 'Guts': | ||||
| 				case 'UserBView': case 'UserSViewBegin': case 'UserSViewEnd': | ||||
| 				case 'Pane': break; | ||||
| 				default: switch(R.n) { /* nested */ | ||||
| @ -824,6 +828,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 	wb.Strings = sst; | ||||
| 	wb.SSF = SSF.get_table(); | ||||
| 	if(opts.enc) wb.Encryption = opts.enc; | ||||
| 	if(themes) wb.Themes = themes; | ||||
| 	wb.Metadata = {}; | ||||
| 	if(country !== undefined) wb.Metadata.Country = country; | ||||
| 	if(supbooks.names.length > 0) Workbook.Names = supbooks.names; | ||||
| @ -838,22 +843,24 @@ function parse_props(cfb/*:CFBContainer*/, props, o) { | ||||
| 	if(DSI) try { | ||||
| 		var DocSummary = parse_PropertySetStream(DSI, DocSummaryPIDDSI); | ||||
| 		for(var d in DocSummary) props[d] = DocSummary[d]; | ||||
| 	} catch(e) {if(o.WTF == 2) throw e;/* empty */} | ||||
| 	} catch(e) {if(o.WTF) throw e;/* empty */} | ||||
| 
 | ||||
| 	/* [MS-OSHARED] 2.3.3.2.1 Summary Information Property Set*/ | ||||
| 	var SI = CFB.find(cfb, '!SummaryInformation'); | ||||
| 	if(SI) try { | ||||
| 		var Summary = parse_PropertySetStream(SI, SummaryPIDSI); | ||||
| 		for(var s in Summary) if(props[s] == null) props[s] = Summary[s]; | ||||
| 	} catch(e) {if(o.WTF == 2) throw e;/* empty */} | ||||
| 	} catch(e) {if(o.WTF) throw e;/* empty */} | ||||
| } | ||||
| 
 | ||||
| function parse_xlscfb(cfb/*:any*/, options/*:?ParseOpts*/)/*:Workbook*/ { | ||||
| if(!options) options = {}; | ||||
| fix_read_opts(options); | ||||
| reset_cp(); | ||||
| if(options.codepage) set_ansi(options.codepage); | ||||
| var CompObj/*:?CFBEntry*/, Summary, WB/*:?any*/; | ||||
| if(cfb.FullPaths) { | ||||
| 	if(CFB.find(cfb, '/encryption')) throw new Error("File is password-protected"); | ||||
| 	CompObj = CFB.find(cfb, '!CompObj'); | ||||
| 	Summary = CFB.find(cfb, '!SummaryInformation'); | ||||
| 	WB = CFB.find(cfb, '/Workbook') || CFB.find(cfb, '/Book'); | ||||
| @ -900,6 +907,8 @@ function write_xlscfb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:CFBContainer*/ { | ||||
| 	switch(o.bookType || "xls") { | ||||
| 		case "xls": o.bookType = "biff8"; | ||||
| 		/* falls through */ | ||||
| 		case "xla": if(!o.bookType) o.bookType = "xla"; | ||||
| 		/* falls through */ | ||||
| 		case "biff8": wbpath = "/Workbook"; o.biff = 8; break; | ||||
| 		case "biff5": wbpath = "/Book"; o.biff = 5; break; | ||||
| 		default: throw new Error("invalid type " + o.bookType + " for XLS CFB"); | ||||
|  | ||||
| @ -72,7 +72,7 @@ var XLSBRecordEnum = { | ||||
| 	/*::[*/0x0086/*::]*/: { n:"BrtEndWsViews" }, | ||||
| 	/*::[*/0x0087/*::]*/: { n:"BrtBeginBookViews" }, | ||||
| 	/*::[*/0x0088/*::]*/: { n:"BrtEndBookViews" }, | ||||
| 	/*::[*/0x0089/*::]*/: { n:"BrtBeginWsView" }, | ||||
| 	/*::[*/0x0089/*::]*/: { n:"BrtBeginWsView", f:parse_BrtBeginWsView }, | ||||
| 	/*::[*/0x008A/*::]*/: { n:"BrtEndWsView" }, | ||||
| 	/*::[*/0x008B/*::]*/: { n:"BrtBeginCsViews" }, | ||||
| 	/*::[*/0x008C/*::]*/: { n:"BrtEndCsViews" }, | ||||
| @ -1026,7 +1026,7 @@ var XLSRecordEnum = { | ||||
| 	/*::[*/0x0221/*::]*/: { n:"Array", f:parse_Array }, | ||||
| 	/*::[*/0x0225/*::]*/: { n:"DefaultRowHeight", f:parse_DefaultRowHeight }, | ||||
| 	/*::[*/0x0236/*::]*/: { n:"Table" }, | ||||
| 	/*::[*/0x023e/*::]*/: { n:"Window2" }, | ||||
| 	/*::[*/0x023e/*::]*/: { n:"Window2", f:parse_Window2 }, | ||||
| 	/*::[*/0x027e/*::]*/: { n:"RK", f:parse_RK }, | ||||
| 	/*::[*/0x0293/*::]*/: { n:"Style" }, | ||||
| 	/*::[*/0x0406/*::]*/: { n:"Formula", f:parse_Formula }, | ||||
|  | ||||
| @ -1,8 +1,8 @@ | ||||
| function write_biff_rec(ba/*:BufArray*/, type/*:number|string*/, payload, length/*:?number*/) { | ||||
| function write_biff_rec(ba/*:BufArray*/, type/*:number|string*/, payload, length/*:?number*/)/*:void*/ { | ||||
| 	var t/*:number*/ = +type || +XLSRE[/*::String(*/type/*::)*/]; | ||||
| 	if(isNaN(t)) return; | ||||
| 	var len = length || (payload||[]).length || 0; | ||||
| 	var o = ba.next(4 + len); | ||||
| 	var o = ba.next(4); | ||||
| 	o.write_shift(2, t); | ||||
| 	o.write_shift(2, len); | ||||
| 	if(/*:: len != null &&*/len > 0 && is_buf(payload)) ba.push(payload); | ||||
| @ -12,8 +12,7 @@ function write_BIFF2Cell(out, r/*:number*/, c/*:number*/) { | ||||
| 	if(!out) out = new_buf(7); | ||||
| 	out.write_shift(2, r); | ||||
| 	out.write_shift(2, c); | ||||
| 	out.write_shift(1, 0); | ||||
| 	out.write_shift(1, 0); | ||||
| 	out.write_shift(2, 0); | ||||
| 	out.write_shift(1, 0); | ||||
| 	return out; | ||||
| } | ||||
| @ -114,7 +113,8 @@ function write_ws_biff8_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:n | ||||
| function write_ws_biff8(idx/*:number*/, opts, wb/*:Workbook*/) { | ||||
| 	var ba = buf_array(); | ||||
| 	var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {}; | ||||
| 	var _sheet/*:WBWSProp*/ = ((((wb||{}).Workbook||{}).Sheets||[])[idx]||{}/*:any*/); | ||||
| 	var _WB/*:WBWBProps*/ = ((wb||{}).Workbook||{}/*:any*/); | ||||
| 	var _sheet/*:WBWSProp*/ = ((_WB.Sheets||[])[idx]||{}/*:any*/); | ||||
| 	var dense = Array.isArray(ws); | ||||
| 	var ref/*:string*/, rr = "", cols/*:Array<string>*/ = []; | ||||
| 	var range = safe_decode_range(ws['!ref'] || "A1"); | ||||
| @ -153,6 +153,10 @@ function write_ws_biff8(idx/*:number*/, opts, wb/*:Workbook*/) { | ||||
| 	} | ||||
| 	var cname/*:string*/ = _sheet.CodeName || _sheet.name || s; | ||||
| 	/* ... */ | ||||
| 	if(b8 && _WB.Views) write_biff_rec(ba, "Window2", write_Window2(_WB.Views[0])); | ||||
| 	/* ... */ | ||||
| 	if(b8) write_biff_rec(ba, "MergeCells", write_MergeCells(ws['!merges']||[])); | ||||
| 	/* ... */ | ||||
| 	if(b8) write_ws_biff8_hlinks(ba, ws); | ||||
| 	/* ... */ | ||||
| 	write_biff_rec(ba, "CodeName", write_XLUnicodeString(cname, opts)); | ||||
| @ -167,6 +171,7 @@ function write_biff8_global(wb/*:Workbook*/, bufs, opts/*:WriteOpts*/) { | ||||
| 	var _wb/*:WBWBProps*/ = /*::((*/(wb.Workbook||{}).WBProps||{/*::CodeName:"ThisWorkbook"*/}/*:: ):any)*/; | ||||
| 	var b8 = opts.biff == 8, b5 = opts.biff == 5; | ||||
| 	write_biff_rec(A, 0x0809, write_BOF(wb, 0x05, opts)); | ||||
| 	if(opts.bookType == "xla") write_biff_rec(A, "Addin"); | ||||
| 	write_biff_rec(A, "InterfaceHdr", b8 ? writeuint16(0x04b0) : null); | ||||
| 	write_biff_rec(A, "Mms", writezeroes(2)); | ||||
| 	if(b5) write_biff_rec(A, "ToolbarHdr"); | ||||
|  | ||||
| @ -10,8 +10,8 @@ var HTML_ = (function() { | ||||
| 		var i/*:number*/ = mtch.index, j/*:number*/ = mtch2 && mtch2.index || str.length; | ||||
| 		var rows = split_regex(str.slice(i, j), /(:?<tr[^>]*>)/i, "<tr>"); | ||||
| 		var R = -1, C = 0, RS = 0, CS = 0; | ||||
| 		var range = {s:{r:10000000, c:10000000},e:{r:0,c:0}}; | ||||
| 		var merges = [], midx = 0; | ||||
| 		var range/*:Range*/ = {s:{r:10000000, c:10000000},e:{r:0,c:0}}; | ||||
| 		var merges/*:Array<Range>*/ = [], midx = 0; | ||||
| 		for(i = 0; i < rows.length; ++i) { | ||||
| 			var row = rows[i].trim(); | ||||
| 			var hd = row.substr(0,3).toLowerCase(); | ||||
| @ -56,8 +56,8 @@ var HTML_ = (function() { | ||||
| 		return sheet_to_workbook(html_to_sheet(str, opts), opts); | ||||
| 	} | ||||
| 	function make_html_row(ws/*:Worksheet*/, r/*:Range*/, R/*:number*/, o/*:Sheet2HTMLOpts*/)/*:string*/ { | ||||
| 		var M = (ws['!merges'] ||[]); | ||||
| 		var oo = []; | ||||
| 		var M/*:Array<Range>*/ = (ws['!merges'] ||[]); | ||||
| 		var oo/*:Array<string>*/ = []; | ||||
| 		var nullcell = "<td>" + (o.editable ? '<span contenteditable="true"></span>' : "" ) + "</td>"; | ||||
| 		for(var C = r.s.c; C <= r.e.c; ++C) { | ||||
| 			var RS = 0, CS = 0; | ||||
| @ -85,7 +85,7 @@ var HTML_ = (function() { | ||||
| 		return preamble + oo.join("") + "</tr>"; | ||||
| 	} | ||||
| 	function make_html_preamble(ws/*:Worksheet*/, R/*:Range*/, o/*:Sheet2HTMLOpts*/)/*:string*/ { | ||||
| 		var out = []; | ||||
| 		var out/*:Array<string>*/ = []; | ||||
| 		return out.join("") + '<table>'; | ||||
| 	} | ||||
| 	var _BEGIN = '<html><head><meta charset="utf-8"/><title>SheetJS Table Export</title></head><body>'; | ||||
| @ -118,17 +118,17 @@ function parse_dom_table(table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ { | ||||
| 	var opts = _opts || {}; | ||||
| 	if(DENSE != null) opts.dense = DENSE; | ||||
| 	var ws/*:Worksheet*/ = opts.dense ? ([]/*:any*/) : ({}/*:any*/); | ||||
| 	var rows = table.getElementsByTagName('tr'); | ||||
| 	var range = {s:{r:0,c:0},e:{r:rows.length - 1,c:0}}; | ||||
| 	var merges = [], midx = 0; | ||||
| 	var rows/*:HTMLCollection<HTMLTableRowElement>*/ = table.getElementsByTagName('tr'); | ||||
| 	var range/*:Range*/ = {s:{r:0,c:0},e:{r:rows.length - 1,c:0}}; | ||||
| 	var merges/*:Array<Range>*/ = [], midx = 0; | ||||
| 	var R = 0, _C = 0, C = 0, RS = 0, CS = 0; | ||||
| 	for(; R < rows.length; ++R) { | ||||
| 		var row = rows[R]; | ||||
| 		var elts = row.children; | ||||
| 		var row/*:HTMLTableRowElement*/ = rows[R]; | ||||
| 		var elts/*:HTMLCollection<HTMLTableCellElement>*/ = (row.children/*:any*/); | ||||
| 		for(_C = C = 0; _C < elts.length; ++_C) { | ||||
| 			var elt = elts[_C], v = htmldecode(elts[_C].innerHTML); | ||||
| 			var elt/*:HTMLTableCellElement*/ = elts[_C], v = htmldecode(elts[_C].innerHTML); | ||||
| 			for(midx = 0; midx < merges.length; ++midx) { | ||||
| 				var m = merges[midx]; | ||||
| 				var m/*:Range*/ = merges[midx]; | ||||
| 				if(m.s.c == C && m.s.r <= R && R <= m.e.r) { C = m.e.c+1; midx = -1; } | ||||
| 			} | ||||
| 			/* TODO: figure out how to extract nonstandard mso- style */ | ||||
|  | ||||
| @ -45,13 +45,13 @@ var parse_content_xml = (function() { | ||||
| 		var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}}; | ||||
| 		var row_ol = 0; | ||||
| 		var number_format_map = {}; | ||||
| 		var merges = [], mrange = {}, mR = 0, mC = 0; | ||||
| 		var rowinfo = [], rowpeat = 1, colpeat = 1; | ||||
| 		var arrayf = []; | ||||
| 		var merges/*:Array<Range>*/ = [], mrange = {}, mR = 0, mC = 0; | ||||
| 		var rowinfo/*:Array<RowInfo>*/ = [], rowpeat = 1, colpeat = 1; | ||||
| 		var arrayf/*:Array<[Range, string]>*/ = []; | ||||
| 		var WB = {Names:[]}; | ||||
| 		var atag = ({}/*:any*/); | ||||
| 		var _Ref/*:[string, string]*/ = ["", ""]; | ||||
| 		var comments = [], comment = {}; | ||||
| 		var comments/*:Array<Comment>*/ = [], comment/*:Comment*/ = ({}/*:any*/); | ||||
| 		var creator = "", creatoridx = 0; | ||||
| 		var isstub = false, intable = false; | ||||
| 		var i = 0; | ||||
| @ -122,7 +122,7 @@ var parse_content_xml = (function() { | ||||
| 					if(C < range.s.c) range.s.c = C; | ||||
| 					if(R < range.s.r) range.s.r = R; | ||||
| 					ctag = parsexmltag(Rn[0], false); | ||||
| 					comments = []; comment = {}; | ||||
| 					comments = []; comment = ({}/*:any*/); | ||||
| 					q = ({t:ctag['数据类型'] || ctag['value-type'], v:null/*:: , z:null, w:"",c:[]*/}/*:any*/); | ||||
| 					if(opts.cellFormula) { | ||||
| 						if(ctag.formula) ctag.formula = unescapexml(ctag.formula); | ||||
|  | ||||
| @ -32,10 +32,10 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = (function() { | ||||
| 	var covered_cell_xml = '          <table:covered-table-cell/>\n'; | ||||
| 	var write_ws = function(ws, wb/*:Workbook*/, i/*:number*/, opts)/*:string*/ { | ||||
| 		/* Section 9 Tables */ | ||||
| 		var o = []; | ||||
| 		var o/*:Array<string>*/ = []; | ||||
| 		o.push('      <table:table table:name="' + escapexml(wb.SheetNames[i]) + '">\n'); | ||||
| 		var R=0,C=0, range = decode_range(ws['!ref']); | ||||
| 		var marr = ws['!merges'] || [], mi = 0; | ||||
| 		var marr/*:Array<Range>*/ = ws['!merges'] || [], mi = 0; | ||||
| 		var dense = Array.isArray(ws); | ||||
| 		for(R = 0; R < range.s.r; ++R) o.push('        <table:table-row></table:table-row>\n'); | ||||
| 		for(; R <= range.e.r; ++R) { | ||||
| @ -186,7 +186,7 @@ function write_ods(wb/*:any*/, opts/*:any*/) { | ||||
| 	var f = ""; | ||||
| 
 | ||||
| 	var manifest/*:Array<Array<string> >*/ = []; | ||||
| 	var rdf = []; | ||||
| 	var rdf/*:Array<[string, string]>*/ = []; | ||||
| 
 | ||||
| 	/* Part 3 Section 3.3 MIME Media Type */ | ||||
| 	f = "mimetype"; | ||||
|  | ||||
| @ -43,7 +43,6 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ { | ||||
| 	make_ssf(SSF); | ||||
| 	opts = opts || {}; | ||||
| 	fix_read_opts(opts); | ||||
| 	reset_cp(); | ||||
| 
 | ||||
| 	/* OpenDocument Part 3 Section 2.2.1 OpenDocument Package */ | ||||
| 	if(safegetzipfile(zip, 'META-INF/manifest.xml')) return parse_ods(zip, opts); | ||||
| @ -67,7 +66,6 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ { | ||||
| 		xlsb = true; | ||||
| 	} | ||||
| 	if(dir.workbooks[0].slice(-3) == "bin") xlsb = true; | ||||
| 	if(xlsb) set_cp(1200); | ||||
| 
 | ||||
| 	var themes = ({}/*:any*/); | ||||
| 	var styles = ({}/*:any*/); | ||||
|  | ||||
| @ -13,7 +13,7 @@ function write_zip(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ { | ||||
| 	opts.rels = {}; opts.wbrels = {}; | ||||
| 	opts.Strings = /*::((*/[]/*:: :any):SST)*/; opts.Strings.Count = 0; opts.Strings.Unique = 0; | ||||
| 	var wbext = opts.bookType == "xlsb" ? "bin" : "xml"; | ||||
| 	var vbafmt = opts.bookType == "xlsb" || opts.bookType == "xlsm"; | ||||
| 	var vbafmt = VBAFMTS.indexOf(opts.bookType) > -1; | ||||
| 	var ct = new_ct(); | ||||
| 	fix_write_opts(opts = opts || {}); | ||||
| 	/*:: if(!jszip) throw new Error("JSZip is not available"); */ | ||||
|  | ||||
| @ -70,7 +70,9 @@ function read_prn(data, d, o, str) { | ||||
| } | ||||
| 
 | ||||
| function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ { | ||||
| 	var zip, d = data, n = [0,0,0,0], str = false; | ||||
| 	reset_cp(); | ||||
| 	if(typeof ArrayBuffer !== 'undefined' && data instanceof ArrayBuffer) return readSync(new Uint8Array(data), opts); | ||||
| 	var d = data, n = [0,0,0,0], str = false; | ||||
| 	var o = opts||{}; | ||||
| 	_ssfopts = {}; | ||||
| 	if(o.dateNF) _ssfopts.dateNF = o.dateNF; | ||||
|  | ||||
| @ -79,6 +79,7 @@ function write_binary_type(out, opts/*:WriteOpts*/)/*:any*/ { | ||||
| function writeSync(wb/*:Workbook*/, opts/*:?WriteOpts*/) { | ||||
| 	check_wb(wb); | ||||
| 	var o = opts||{}; | ||||
| 	if(o.type == "array") { o.type = "binary"; var out/*:string*/ = (writeSync(wb, o)/*:any*/); o.type = "array"; return s2ab(out); } | ||||
| 	switch(o.bookType || 'xlsb') { | ||||
| 		case 'xml': | ||||
| 		case 'xlml': return write_string_type(write_xlml(wb, o), o); | ||||
| @ -99,9 +100,11 @@ function writeSync(wb/*:Workbook*/, opts/*:?WriteOpts*/) { | ||||
| 		case 'biff4': if(!o.biff) o.biff = 4; return write_binary_type(write_biff_buf(wb, o), o); | ||||
| 		case 'biff5': if(!o.biff) o.biff = 5; /* falls through */ | ||||
| 		case 'biff8': | ||||
| 		case 'xla': | ||||
| 		case 'xls': if(!o.biff) o.biff = 8; return write_cfb_type(wb, o); | ||||
| 		case 'xlsx': | ||||
| 		case 'xlsm': | ||||
| 		case 'xlam': | ||||
| 		case 'xlsb': | ||||
| 		case 'ods': return write_zip_type(wb, o); | ||||
| 		default: throw new Error ("Unrecognized bookType |" + o.bookType + "|"); | ||||
|  | ||||
| @ -103,20 +103,20 @@ function make_csv_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Arr | ||||
| } | ||||
| 
 | ||||
| function sheet_to_csv(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/)/*:string*/ { | ||||
| 	var out = []; | ||||
| 	var out/*:Array<string>*/ = []; | ||||
| 	var o = opts == null ? {} : opts; | ||||
| 	if(sheet == null || sheet["!ref"] == null) return ""; | ||||
| 	var r = safe_decode_range(sheet["!ref"]); | ||||
| 	var FS = o.FS !== undefined ? o.FS : ",", fs = FS.charCodeAt(0); | ||||
| 	var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0); | ||||
| 	var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$"); | ||||
| 	var row = "", cols = []; | ||||
| 	var row = "", cols/*:Array<string>*/ = []; | ||||
| 	o.dense = Array.isArray(sheet); | ||||
| 	var colInfos = o.skipHidden && sheet["!cols"] || []; | ||||
| 	var rowInfos = o.skipHidden && sheet["!rows"] || []; | ||||
| 	for(var C = r.s.c; C <= r.e.c; ++C) if (!((colInfos[C]||{}).hidden)) cols[C] = encode_col(C); | ||||
| 	var colinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!cols"] || []; | ||||
| 	var rowinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!rows"] || []; | ||||
| 	for(var C = r.s.c; C <= r.e.c; ++C) if (!((colinfo[C]||{}).hidden)) cols[C] = encode_col(C); | ||||
| 	for(var R = r.s.r; R <= r.e.r; ++R) { | ||||
| 		if ((rowInfos[R]||{}).hidden) continue; | ||||
| 		if ((rowinfo[R]||{}).hidden) continue; | ||||
| 		row = make_csv_row(sheet, r, R, cols, fs, rs, FS, o); | ||||
| 		if(row == null) { continue; } | ||||
| 		if(o.strip) row = row.replace(endregex,""); | ||||
| @ -137,7 +137,7 @@ function sheet_to_txt(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) { | ||||
| function sheet_to_formulae(sheet/*:Worksheet*/)/*:Array<string>*/ { | ||||
| 	var y = "", x, val=""; | ||||
| 	if(sheet == null || sheet["!ref"] == null) return []; | ||||
| 	var r = safe_decode_range(sheet['!ref']), rr = "", cols = [], C; | ||||
| 	var r = safe_decode_range(sheet['!ref']), rr = "", cols/*:Array<string>*/ = [], C; | ||||
| 	var cmds/*:Array<string>*/ = []; | ||||
| 	var dense = Array.isArray(sheet); | ||||
| 	for(C = r.s.c; C <= r.e.c; ++C) cols[C] = encode_col(C); | ||||
| @ -173,7 +173,7 @@ function json_to_sheet(js/*:Array<any>*/, opts)/*:Worksheet*/ { | ||||
| 	var ws = ({}/*:any*/); | ||||
| 	var cell/*:Cell*/; | ||||
| 	var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:0, r:js.length}}/*:any*/); | ||||
| 	var hdr = o.header || [], C = 0; | ||||
| 	var hdr/*:Array<string>*/ = o.header || [], C = 0; | ||||
| 
 | ||||
| 	js.forEach(function (JS, R) { | ||||
| 		keys(JS).filter(function(x) { return JS.hasOwnProperty(x); }).forEach(function(k) { | ||||
|  | ||||
| @ -10,17 +10,17 @@ if(has_buf && typeof require != 'undefined') (function() { | ||||
| 		var FS = o.FS !== undefined ? o.FS : ",", fs = FS.charCodeAt(0); | ||||
| 		var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0); | ||||
| 		var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$"); | ||||
| 		var row/*:?string*/ = "", cols = []; | ||||
| 		var row/*:?string*/ = "", cols/*:Array<string>*/ = []; | ||||
| 		o.dense = Array.isArray(sheet); | ||||
| 		var colInfos = o.skipHidden && sheet["!cols"] || []; | ||||
| 		var rowInfos = o.skipHidden && sheet["!rows"] || []; | ||||
| 		for(var C = r.s.c; C <= r.e.c; ++C) if (!((colInfos[C]||{}).hidden)) cols[C] = encode_col(C); | ||||
| 		var colinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!cols"] || []; | ||||
| 		var rowinfo/*:Array<RowInfo>*/ = o.skipHidden && sheet["!rows"] || []; | ||||
| 		for(var C = r.s.c; C <= r.e.c; ++C) if (!((colinfo[C]||{}).hidden)) cols[C] = encode_col(C); | ||||
| 		var R = r.s.r; | ||||
| 		stream._read = function() { | ||||
| 			if(R > r.e.r) return stream.push(null); | ||||
| 			while(R <= r.e.r) { | ||||
| 				++R; | ||||
| 				if ((rowInfos[R-1]||{}).hidden) continue; | ||||
| 				if ((rowinfo[R-1]||{}).hidden) continue; | ||||
| 				row = make_csv_row(sheet, r, R-1, cols, fs, rs, FS, o); | ||||
| 				if(row != null) { | ||||
| 					if(o.strip) row = row.replace(endregex,""); | ||||
|  | ||||
| @ -1,5 +1,3 @@ | ||||
| })(typeof exports !== 'undefined' ? exports : XLSX); | ||||
| /*exported XLS */ | ||||
| var XLS = XLSX; | ||||
| /*exported ODS */ | ||||
| var ODS = XLSX; | ||||
| /*exported XLS, ODS */ | ||||
| var XLS = XLSX, ODS = XLSX; | ||||
|  | ||||
| @ -81,18 +81,11 @@ var ws = XLSX.utils.json_to_sheet(data); | ||||
| var wb = XLSX.utils.book_new(); | ||||
| XLSX.utils.book_append_sheet(wb, ws, "Presidents"); | ||||
| 
 | ||||
| /* write workbook (use type 'binary') */ | ||||
| var wbout = XLSX.write(wb, {bookType:'xlsx', type:'binary'}); | ||||
| /* write workbook (use type 'array' for ArrayBuffer) */ | ||||
| var wbout = XLSX.write(wb, {bookType:'xlsx', type:'array'}); | ||||
| 
 | ||||
| /* generate a download */ | ||||
| function s2ab(s) { | ||||
|   var buf = new ArrayBuffer(s.length); | ||||
|   var view = new Uint8Array(buf); | ||||
|   for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF; | ||||
|   return buf; | ||||
| } | ||||
| 
 | ||||
| saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), "sheetjs.xlsx"); | ||||
| saveAs(new Blob([wbout],{type:"application/octet-stream"}), "sheetjs.xlsx"); | ||||
| ``` | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										19
									
								
								demos/angular/SheetJS-angular.js
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										19
									
								
								demos/angular/SheetJS-angular.js
									
									
									
									
										vendored
									
									
								
							| @ -13,12 +13,12 @@ function SheetJSExportService(uiGridExporterService) { | ||||
| 		var wb = XLSX.utils.book_new(), ws = uigrid_to_sheet(data, columns); | ||||
| 		XLSX.utils.book_append_sheet(wb, ws, sheetName); | ||||
| 		var wbout = XLSX.write(wb, wopts); | ||||
| 		saveAs(new Blob([s2ab(wbout)], { type: 'application/octet-stream' }), fileName); | ||||
| 		saveAs(new Blob([wbout], { type: 'application/octet-stream' }), fileName); | ||||
| 	} | ||||
| 
 | ||||
| 	var service = {}; | ||||
| 	service.exportXLSB = function exportXLSB(gridApi) { return exportSheetJS(gridApi, { bookType: 'xlsb', bookSST: true, type: 'binary' }); }; | ||||
| 	service.exportXLSX = function exportXLSX(gridApi) { return exportSheetJS(gridApi, { bookType: 'xlsx', bookSST: true, type: 'binary' }); } | ||||
| 	service.exportXLSB = function exportXLSB(gridApi) { return exportSheetJS(gridApi, { bookType: 'xlsb', bookSST: true, type: 'array' }); }; | ||||
| 	service.exportXLSX = function exportXLSX(gridApi) { return exportSheetJS(gridApi, { bookType: 'xlsx', bookSST: true, type: 'array' }); } | ||||
| 
 | ||||
| 	return service; | ||||
| 
 | ||||
| @ -47,19 +47,6 @@ function SheetJSExportService(uiGridExporterService) { | ||||
| 		if(col.name) return col.name; | ||||
| 		return null; | ||||
| 	} | ||||
| 
 | ||||
| 	function s2ab(s) { | ||||
| 		if(typeof ArrayBuffer !== 'undefined') { | ||||
| 			var buf = new ArrayBuffer(s.length); | ||||
| 			var view = new Uint8Array(buf); | ||||
| 			for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF; | ||||
| 			return buf; | ||||
| 		} else { | ||||
| 			var buf = new Array(s.length); | ||||
| 			for (var i=0; i!=s.length; ++i) buf[i] = s.charCodeAt(i) & 0xFF; | ||||
| 			return buf; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| var SheetJSImportDirective = function() { | ||||
|  | ||||
| @ -35,8 +35,8 @@ const wb: XLSX.WorkBook = XLSX.utils.book_new(); | ||||
| XLSX.utils.book_append_sheet(wb, ws, 'Sheet1'); | ||||
| 
 | ||||
| /* save to file */ | ||||
| const wbout: string = XLSX.write(wb, { bookType: 'xlsx', type: 'binary' }); | ||||
| saveAs(new Blob([s2ab(wbout)]), 'SheetJS.xlsx'); | ||||
| const wbout: string = XLSX.write(wb, { bookType: 'xlsx', type: 'array' }); | ||||
| saveAs(new Blob([wbout]), 'SheetJS.xlsx'); | ||||
| ``` | ||||
| 
 | ||||
| `sheet_to_json` with the option `header:1` makes importing simple: | ||||
|  | ||||
| @ -8,13 +8,6 @@ import { saveAs } from 'file-saver'; | ||||
| 
 | ||||
| type AOA = Array<Array<any>>; | ||||
| 
 | ||||
| function s2ab(s: string): ArrayBuffer { | ||||
| 	const buf: ArrayBuffer = new ArrayBuffer(s.length); | ||||
| 	const view: Uint8Array = new Uint8Array(buf); | ||||
| 	for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF; | ||||
| 	return buf; | ||||
| } | ||||
| 
 | ||||
| @Component({ | ||||
| 	selector: 'sheetjs', | ||||
| 	template: ` | ||||
| @ -32,7 +25,7 @@ function s2ab(s: string): ArrayBuffer { | ||||
| 
 | ||||
| export class SheetJSComponent { | ||||
| 	data: AOA = [ [1, 2], [3, 4] ]; | ||||
| 	wopts: XLSX.WritingOptions = { bookType: 'xlsx', type: 'binary' }; | ||||
| 	wopts: XLSX.WritingOptions = { bookType: 'xlsx', type: 'array' }; | ||||
| 	fileName: string = 'SheetJS.xlsx'; | ||||
| 
 | ||||
| 	onFileChange(evt: any) { | ||||
| @ -64,7 +57,7 @@ export class SheetJSComponent { | ||||
| 		XLSX.utils.book_append_sheet(wb, ws, 'Sheet1'); | ||||
| 
 | ||||
| 		/* save to file */ | ||||
| 		const wbout: string = XLSX.write(wb, this.wopts); | ||||
| 		saveAs(new Blob([s2ab(wbout)]), this.fileName); | ||||
| 		const wbout: ArrayBuffer = XLSX.write(wb, this.wopts); | ||||
| 		saveAs(new Blob([wbout], { type: 'application/octet-stream' }), this.fileName); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -71,6 +71,9 @@ var process_wb = (function() { | ||||
| 		var range = XLSX.utils.decode_range(ws['!ref']); | ||||
| 		for(var i = range.s.c; i <= range.e.c; ++i) cDg.schema[i - range.s.c].title = XLSX.utils.encode_col(i); | ||||
| 
 | ||||
| 		HTMLOUT.style.height = (window.innerHeight - 400) + "px"; | ||||
| 		HTMLOUT.style.width = (window.innerWidth - 50) + "px"; | ||||
| 
 | ||||
| 		if(typeof console !== 'undefined') console.log("output", new Date()); | ||||
| 	}; | ||||
| })(); | ||||
| @ -136,12 +139,6 @@ var export_xlsx = (function() { | ||||
| 		return out; | ||||
| 	} | ||||
| 
 | ||||
| 	function s2ab(s) { | ||||
| 		var b = new ArrayBuffer(s.length), v = new Uint8Array(b); | ||||
| 		for (var i=0; i != s.length; ++i) v[i] = s.charCodeAt(i) & 0xFF; | ||||
| 		return b; | ||||
| 	} | ||||
| 
 | ||||
| 	return function export_xlsx() { | ||||
| 		if(!cDg) return; | ||||
| 		/* convert canvas-datagrid data to worksheet */ | ||||
| @ -152,10 +149,10 @@ var export_xlsx = (function() { | ||||
| 		XLSX.utils.book_append_sheet(new_wb, new_ws, 'SheetJS'); | ||||
| 
 | ||||
| 		/* write file and trigger a download */ | ||||
| 		var wbout = XLSX.write(new_wb, {bookType:'xlsx', bookSST:true, type:'binary'}); | ||||
| 		var wbout = XLSX.write(new_wb, {bookType:'xlsx', bookSST:true, type:'array'}); | ||||
| 		var fname = 'sheetjs.xlsx'; | ||||
| 		try { | ||||
| 			saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), fname); | ||||
| 			saveAs(new Blob([wbout],{type:"application/octet-stream"}), fname); | ||||
| 		} catch(e) { if(typeof console != 'undefined') console.log(e, wbout); } | ||||
| 	}; | ||||
| })(); | ||||
|  | ||||
| @ -61,8 +61,8 @@ const html = document.getElementById('out').innerHTML; | ||||
| // SERVER SIDE | ||||
| const wb = XLSX.read(html, { type: 'binary' }); | ||||
| // CLIENT SIDE | ||||
| const o = XLSX.write(wb, { bookType: 'xlsx', type: 'binary' }); | ||||
| saveAs(new Blob([s2ab(o)], {type:'application/octet-stream'}), 'sheetjs.xlsx'); | ||||
| const o = XLSX.write(wb, { bookType: 'xlsx', type: 'array' }); | ||||
| saveAs(new Blob([o], {type:'application/octet-stream'}), 'sheetjs.xlsx'); | ||||
| ``` | ||||
| 
 | ||||
| This demo uses the FileSaver library for writing files, installed through the | ||||
|  | ||||
| @ -34,16 +34,9 @@ Template.sheetjs.events({ | ||||
|     Meteor.call('download', html, function(err, wb) { | ||||
|       if (err) throw err; | ||||
|       /* "Browser download file" from SheetJS README */ | ||||
|       const wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'binary' }); | ||||
|       saveAs(new Blob([s2ab(wbout)], { type: 'application/octet-stream' }), 'sheetjs.xlsx'); | ||||
|       const wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'array' }); | ||||
|       saveAs(new Blob([wbout], { type: 'application/octet-stream' }), 'sheetjs.xlsx'); | ||||
|     }); | ||||
|   }, | ||||
| }); | ||||
| 
 | ||||
| /* eslint no-bitwise:0, no-plusplus:0 */ | ||||
| function s2ab(s) { | ||||
|   const buf = new ArrayBuffer(s.length); | ||||
|   const view = new Uint8Array(buf); | ||||
|   for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF; | ||||
|   return buf; | ||||
| } | ||||
|  | ||||
| @ -9,7 +9,7 @@ | ||||
| <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script> | ||||
| <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react.min.js"></script> | ||||
| <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react-dom.min.js"></script> | ||||
| <script src="https://unpkg.com/xlsx/dist/xlsx.full.min.js"></script> | ||||
| <script src="node_modules/xlsx/dist/xlsx.full.min.js"></script> | ||||
| <script src="https://unpkg.com/file-saver/FileSaver.js"></script> | ||||
| <style>body, #app { height: 100%; };</style> | ||||
| </head> | ||||
|  | ||||
| @ -38,9 +38,9 @@ class SheetJSApp extends React.Component { | ||||
| 		const wb = XLSX.utils.book_new(); | ||||
| 		XLSX.utils.book_append_sheet(wb, ws, "SheetJS"); | ||||
| 		/* generate XLSX file */ | ||||
| 		const wbout = XLSX.write(wb, {type:"binary", bookType:"xlsx"}); | ||||
| 		const wbout = XLSX.write(wb, {type:"array", bookType:"xlsx"}); | ||||
| 		/* send to client */ | ||||
| 		saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), "sheetjs.xlsx"); | ||||
| 		saveAs(new Blob([wbout],{type:"application/octet-stream"}), "sheetjs.xlsx"); | ||||
| 	}; | ||||
| 	render() { return ( | ||||
| <DragDropFile handleFile={this.handleFile}> | ||||
| @ -136,13 +136,5 @@ const SheetJSFT = [ | ||||
| 	"xlsx", "xlsb", "xlsm", "xls", "xml", "csv", "txt", "ods", "fods", "uos", "sylk", "dif", "dbf", "prn", "qpw", "123", "wb*", "wq*", "html", "htm" | ||||
| ].map(function(x) { return "." + x; }).join(","); | ||||
| 
 | ||||
| /* see Browser download file example in docs */ | ||||
| function s2ab(s/*:string*/)/*:ArrayBuffer*/ { | ||||
|   const buf = new ArrayBuffer(s.length); | ||||
|   const view = new Uint8Array(buf); | ||||
|   for (let i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF; | ||||
|   return buf; | ||||
| } | ||||
| 
 | ||||
| /* generate an array of column objects */ | ||||
| const make_cols = refstr => Array(XLSX.utils.decode_range(refstr).e.c + 1).fill(0).map((x,i) => ({name:XLSX.utils.encode_col(i), key:i})); | ||||
|  | ||||
| @ -95,13 +95,17 @@ fs.writeFileSync("sheetjs.xls", new Buffer(str, "base64")); | ||||
| 
 | ||||
| #### Server-Rendered VueJS Components with Nuxt.js | ||||
| 
 | ||||
| Due to webpack configuration issues on client/server bundles, the library should | ||||
| be explicitly included in the layout HTML (as script tag) and in the component: | ||||
| The scripts should be treated as external resources in `nuxt.config.js`: | ||||
| 
 | ||||
| ```js | ||||
| const _XLSX = require('xlsx'); | ||||
| const X = typeof XLSX !== 'undefined' ? XLSX : _XLSX; | ||||
| /* use the variable X rather than XLSX in the component */ | ||||
| module.exports = { | ||||
| 	head: { | ||||
| 		script: [ | ||||
| 			{ src: "https://unpkg.com/xlsx/dist/xlsx.full.min.js" }, // library | ||||
| 			{ src: "https://unpkg.com/file-saver/FileSaver.js" } // saveAs shim | ||||
| 		] | ||||
| 	} | ||||
| }; | ||||
| ``` | ||||
| 
 | ||||
| [](https://github.com/SheetJS/js-xlsx) | ||||
|  | ||||
| @ -13,19 +13,6 @@ var SJSTemplate = [ | ||||
| 	'</div>' | ||||
| ].join(""); | ||||
| 
 | ||||
| function s2ab(s) { | ||||
| 	if(typeof ArrayBuffer !== 'undefined') { | ||||
| 		var buf = new ArrayBuffer(s.length); | ||||
| 		var view = new Uint8Array(buf); | ||||
| 		for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF; | ||||
| 		return buf; | ||||
| 	} else { | ||||
| 		var buf = new Array(s.length); | ||||
| 		for (var i=0; i!=s.length; ++i) buf[i] = s.charCodeAt(i) & 0xFF; | ||||
| 		return buf; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| Vue.component('html-preview', { | ||||
| 	template: SJSTemplate, | ||||
| 	methods: { | ||||
| @ -69,10 +56,10 @@ Vue.component('html-preview', { | ||||
| 			/* generate workbook object from table */ | ||||
| 			var wb = XLSX.utils.table_to_book(document.getElementById('out-table')); | ||||
| 			/* get binary string as output */ | ||||
| 			var wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'binary' }); | ||||
| 			var wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'array' }); | ||||
| 
 | ||||
| 			/* force a download */ | ||||
| 			saveAs(new Blob([s2ab(wbout)], { type: 'application/octet-stream' }), "sheetjs.xlsx"); | ||||
| 			saveAs(new Blob([wbout], { type: 'application/octet-stream' }), "sheetjs.xlsx"); | ||||
| 		} | ||||
| 	} | ||||
| }); | ||||
|  | ||||
							
								
								
									
										9
									
								
								demos/vue/nuxt.config.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										9
									
								
								demos/vue/nuxt.config.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| module.exports = { | ||||
| 	head: { | ||||
| 		script: [ | ||||
| 			// { src: "https://unpkg.com/xlsx/dist/xlsx.full.min.js" }, // CDN
 | ||||
| 			{ src: "xlsx.full.min.js" }, // development
 | ||||
| 			{ src: "https://unpkg.com/file-saver/FileSaver.js" } | ||||
| 		] | ||||
| 	} | ||||
| }; | ||||
| @ -30,17 +30,7 @@ | ||||
| </template> | ||||
| 
 | ||||
| <script> | ||||
| const _XLSX = require('xlsx'); | ||||
| const X = typeof XLSX !== 'undefined' ? XLSX : _XLSX; | ||||
| const make_cols = refstr => Array(X.utils.decode_range(refstr).e.c + 1).fill(0).map((x,i) => ({name:X.utils.encode_col(i), key:i})); | ||||
| 
 | ||||
| /* see Browser download file example in docs */ | ||||
| function s2ab(s) { | ||||
|   const buf = new ArrayBuffer(s.length); | ||||
|   const view = new Uint8Array(buf); | ||||
|   for (let i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF; | ||||
|   return buf; | ||||
| } | ||||
| const make_cols = refstr => Array(XLSX.utils.decode_range(refstr).e.c + 1).fill(0).map((x,i) => ({name:XLSX.utils.encode_col(i), key:i})); | ||||
| 
 | ||||
| const _SheetJSFT = [ | ||||
| 	"xlsx", "xlsb", "xlsm", "xls", "xml", "csv", "txt", "ods", "fods", "uos", "sylk", "dif", "dbf", "prn", "qpw", "123", "wb*", "wq*", "html", "htm" | ||||
| @ -73,13 +63,13 @@ export default { | ||||
| 		}, | ||||
| 		_export(evt) { | ||||
| 			/* convert state to workbook */ | ||||
| 			const ws = X.utils.aoa_to_sheet(this.data); | ||||
| 			const wb = X.utils.book_new(); | ||||
| 			X.utils.book_append_sheet(wb, ws, "SheetJS"); | ||||
| 			const ws = XLSX.utils.aoa_to_sheet(this.data); | ||||
| 			const wb = XLSX.utils.book_new(); | ||||
| 			XLSX.utils.book_append_sheet(wb, ws, "SheetJS"); | ||||
| 			/* generate X file */ | ||||
| 			const wbout = X.write(wb, {type:"binary", bookType:"xlsx"}); | ||||
| 			const wbout = XLSX.write(wb, {type:"array", bookType:"xlsx"}); | ||||
| 			/* send to client */ | ||||
| 			saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), "sheetjs.xlsx"); | ||||
| 			saveAs(new Blob([wbout],{type:"application/octet-stream"}), "sheetjs.xlsx"); | ||||
| 		}, | ||||
| 		_file(file) { | ||||
| 			/* Boilerplate to set up FileReader */ | ||||
| @ -87,12 +77,12 @@ export default { | ||||
| 			reader.onload = (e) => { | ||||
| 				/* Parse data */ | ||||
| 				const bstr = e.target.result; | ||||
| 				const wb = X.read(bstr, {type:'binary'}); | ||||
| 				const wb = XLSX.read(bstr, {type:'binary'}); | ||||
| 				/* Get first worksheet */ | ||||
| 				const wsname = wb.SheetNames[0]; | ||||
| 				const ws = wb.Sheets[wsname]; | ||||
| 				/* Convert array of arrays */ | ||||
| 				const data = X.utils.sheet_to_json(ws, {header:1}); | ||||
| 				const data = XLSX.utils.sheet_to_json(ws, {header:1}); | ||||
| 				/* Update state */ | ||||
| 				this.data = data; | ||||
| 				this.cols = make_cols(ws['!ref']); | ||||
|  | ||||
							
								
								
									
										30
									
								
								dist/xlsx.core.min.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										30
									
								
								dist/xlsx.core.min.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2
									
								
								dist/xlsx.core.min.map
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										2
									
								
								dist/xlsx.core.min.map
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										32
									
								
								dist/xlsx.full.min.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										32
									
								
								dist/xlsx.full.min.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2
									
								
								dist/xlsx.full.min.map
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										2
									
								
								dist/xlsx.full.min.map
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										614
									
								
								dist/xlsx.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										614
									
								
								dist/xlsx.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										24
									
								
								dist/xlsx.min.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										24
									
								
								dist/xlsx.min.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2
									
								
								dist/xlsx.min.map
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										2
									
								
								dist/xlsx.min.map
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @ -43,19 +43,12 @@ example uses [FileSaver](https://github.com/eligrey/FileSaver.js/): | ||||
| 
 | ||||
| ```js | ||||
| /* bookType can be any supported output type */ | ||||
| var wopts = { bookType:'xlsx', bookSST:false, type:'binary' }; | ||||
| var wopts = { bookType:'xlsx', bookSST:false, type:'array' }; | ||||
| 
 | ||||
| var wbout = XLSX.write(workbook,wopts); | ||||
| 
 | ||||
| function s2ab(s) { | ||||
|   var buf = new ArrayBuffer(s.length); | ||||
|   var view = new Uint8Array(buf); | ||||
|   for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF; | ||||
|   return buf; | ||||
| } | ||||
| 
 | ||||
| /* the saveAs call downloads a file on the local machine */ | ||||
| saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), "test.xlsx"); | ||||
| saveAs(new Blob([wbout],{type:"application/octet-stream"}), "test.xlsx"); | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
|  | ||||
| @ -22,6 +22,14 @@ Excel allows two sheet-scoped defined names to share the same name.  However, a | ||||
| sheet-scoped name cannot collide with a workbook-scope name.  Workbook writers | ||||
| may not enforce this constraint. | ||||
| 
 | ||||
| #### Workbook Views | ||||
| 
 | ||||
| `wb.Workbook.Views` is an array of workbook view objects which have the keys: | ||||
| 
 | ||||
| | Key             | Description                                         | | ||||
| |:----------------|:----------------------------------------------------| | ||||
| | `RTL`           | If true, display right-to-left                      | | ||||
| 
 | ||||
| #### Miscellaneous Workbook Properties | ||||
| 
 | ||||
| `wb.Workbook.WBProps` holds other workbook properties: | ||||
|  | ||||
| @ -68,5 +68,6 @@ The `type` argument for `write` mirrors the `type` argument for `read`: | ||||
| | `"binary"` | string: binary string (byte `n` is `data.charCodeAt(n)`)        | | ||||
| | `"string"` | string: JS string (characters interpreted as UTF8)              | | ||||
| | `"buffer"` | nodejs Buffer                                                   | | ||||
| | `"array"`  | ArrayBuffer, fallback array of 8-bit unsigned int               | | ||||
| | `"file"`   | string: path of file that will be created (nodejs only)         | | ||||
| 
 | ||||
|  | ||||
| @ -79,6 +79,7 @@ enhancements, additional features by request, and dedicated support. | ||||
|     + [Workbook File Properties](#workbook-file-properties) | ||||
|   * [Workbook-Level Attributes](#workbook-level-attributes) | ||||
|     + [Defined Names](#defined-names) | ||||
|     + [Workbook Views](#workbook-views) | ||||
|     + [Miscellaneous Workbook Properties](#miscellaneous-workbook-properties) | ||||
|   * [Document Features](#document-features) | ||||
|     + [Formulae](#formulae) | ||||
| @ -565,19 +566,12 @@ example uses [FileSaver](https://github.com/eligrey/FileSaver.js/): | ||||
| 
 | ||||
| ```js | ||||
| /* bookType can be any supported output type */ | ||||
| var wopts = { bookType:'xlsx', bookSST:false, type:'binary' }; | ||||
| var wopts = { bookType:'xlsx', bookSST:false, type:'array' }; | ||||
| 
 | ||||
| var wbout = XLSX.write(workbook,wopts); | ||||
| 
 | ||||
| function s2ab(s) { | ||||
|   var buf = new ArrayBuffer(s.length); | ||||
|   var view = new Uint8Array(buf); | ||||
|   for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF; | ||||
|   return buf; | ||||
| } | ||||
| 
 | ||||
| /* the saveAs call downloads a file on the local machine */ | ||||
| saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), "test.xlsx"); | ||||
| saveAs(new Blob([wbout],{type:"application/octet-stream"}), "test.xlsx"); | ||||
| ``` | ||||
| 
 | ||||
| 
 | ||||
| @ -994,6 +988,14 @@ Excel allows two sheet-scoped defined names to share the same name.  However, a | ||||
| sheet-scoped name cannot collide with a workbook-scope name.  Workbook writers | ||||
| may not enforce this constraint. | ||||
| 
 | ||||
| #### Workbook Views | ||||
| 
 | ||||
| `wb.Workbook.Views` is an array of workbook view objects which have the keys: | ||||
| 
 | ||||
| | Key             | Description                                         | | ||||
| |:----------------|:----------------------------------------------------| | ||||
| | `RTL`           | If true, display right-to-left                      | | ||||
| 
 | ||||
| #### Miscellaneous Workbook Properties | ||||
| 
 | ||||
| `wb.Workbook.WBProps` holds other workbook properties: | ||||
| @ -1558,6 +1560,7 @@ The `type` argument for `write` mirrors the `type` argument for `read`: | ||||
| | `"binary"` | string: binary string (byte `n` is `data.charCodeAt(n)`)        | | ||||
| | `"string"` | string: JS string (characters interpreted as UTF8)              | | ||||
| | `"buffer"` | nodejs Buffer                                                   | | ||||
| | `"array"`  | ArrayBuffer, fallback array of 8-bit unsigned int               | | ||||
| | `"file"`   | string: path of file that will be created (nodejs only)         | | ||||
| 
 | ||||
| ## Utility Functions | ||||
|  | ||||
| @ -32,6 +32,7 @@ | ||||
|     + [Workbook File Properties](README.md#workbook-file-properties) | ||||
|   * [Workbook-Level Attributes](README.md#workbook-level-attributes) | ||||
|     + [Defined Names](README.md#defined-names) | ||||
|     + [Workbook Views](README.md#workbook-views) | ||||
|     + [Miscellaneous Workbook Properties](README.md#miscellaneous-workbook-properties) | ||||
|   * [Document Features](README.md#document-features) | ||||
|     + [Formulae](README.md#formulae) | ||||
|  | ||||
							
								
								
									
										10
									
								
								misc/flow.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										10
									
								
								misc/flow.js
									
									
									
									
									
								
							| @ -27,6 +27,7 @@ type Workbook = { | ||||
| type WBWBProps = { | ||||
| 	Sheets: Array<WBWSProp>; | ||||
| 	Names?: Array<any>; | ||||
| 	Views?: Array<any>; | ||||
| 	WBProps?: WBProps; | ||||
| }; | ||||
| 
 | ||||
| @ -96,7 +97,14 @@ type SST = { | ||||
| 	length:number; | ||||
| }; | ||||
| 
 | ||||
| type Comment = any; | ||||
| type Comment = { | ||||
| 	t:string; | ||||
| 	a?:string; | ||||
| 	r?:string; | ||||
| 	h?:string; | ||||
| }; | ||||
| 
 | ||||
| type RawComment = any; | ||||
| 
 | ||||
| type RowInfo = { | ||||
| 	hidden?:boolean; // if true, the row is hidden
 | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| { | ||||
| 	"name": "xlsx", | ||||
| 	"version": "0.11.15", | ||||
| 	"version": "0.11.16", | ||||
| 	"author": "sheetjs", | ||||
| 	"description": "SheetJS Spreadsheet data parser and writer", | ||||
| 	"keywords": [ | ||||
|  | ||||
							
								
								
									
										22
									
								
								test.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										22
									
								
								test.js
									
									
									
									
									
								
							| @ -655,6 +655,7 @@ describe('output formats', function() { | ||||
| 	it('should write binary strings', function() { RT('binary'); }); | ||||
| 	it('should write base64 strings', function() { RT('base64'); }); | ||||
| 	it('should write JS strings', function() { RT('string'); }); | ||||
| 	if(typeof ArrayBuffer !== 'undefined' && (typeof process == 'undefined' || !process.version.match(/v0.12/))) it('should write array buffers', function() { RT('array'); }); | ||||
| 	if(!browser) it('should write buffers', function() { RT('buffer'); }); | ||||
| 	it('should throw if format is unknown', function() { assert.throws(function() { RT('dafuq'); }); }); | ||||
| }); | ||||
| @ -819,10 +820,10 @@ describe('parse features', function() { | ||||
| 		var wbs=[]; | ||||
| 		var bef = (function() { | ||||
| 			wbs = [ | ||||
| 				X.read(fs.readFileSync(paths.cpxlsx), {type:TYPE}), | ||||
| 				X.read(fs.readFileSync(paths.cpxlsb), {type:TYPE}), | ||||
| 				X.read(fs.readFileSync(paths.cpxls), {type:TYPE}), | ||||
| 				X.read(fs.readFileSync(paths.cpxml), {type:TYPE}) | ||||
| 				X.read(fs.readFileSync(paths.cpxlsx), {type:TYPE, WTF:1}), | ||||
| 				X.read(fs.readFileSync(paths.cpxlsb), {type:TYPE, WTF:1}), | ||||
| 				X.read(fs.readFileSync(paths.cpxls), {type:TYPE, WTF:1}), | ||||
| 				X.read(fs.readFileSync(paths.cpxml), {type:TYPE, WTF:1}) | ||||
| 			]; | ||||
| 		}); | ||||
| 		if(typeof before != 'undefined') before(bef); | ||||
| @ -1319,7 +1320,7 @@ describe('roundtrip features', function() { | ||||
| 	}); }); | ||||
| 
 | ||||
| 	describe('should preserve merge cells', function() { | ||||
| 		["xlsx", "xlsb", "xlml", "ods"].forEach(function(f) { it(f, function() { | ||||
| 		["xlsx", "xlsb", "xlml", "ods", "biff8"].forEach(function(f) { it(f, function() { | ||||
| 			var wb1 = X.read(fs.readFileSync(paths.mcxlsx), {type:TYPE}); | ||||
| 			var wb2 = X.read(X.write(wb1,{bookType:f,type:'binary'}),{type:'binary'}); | ||||
| 			var m1 = wb1.Sheets.Merge['!merges'].map(X.utils.encode_range); | ||||
| @ -1911,8 +1912,15 @@ describe('HTML', function() { | ||||
| 		it('should generate strings if raw option is passed', function() { plaintext_test(X.utils.table_to_book(get_dom_element(html_str), {raw:true}), true, true); }); | ||||
| 		it('should handle newlines correctly', function() { | ||||
| 			var table = get_dom_element("<table><tr><td>foo<br/>bar</td><td>baz</td></tr></table>"); | ||||
| 			var wb = X.utils.table_to_book(table); | ||||
| 			assert.equal(get_cell(wb.Sheets.Sheet1, "A1").v, "foo\nbar"); | ||||
| 			var ws = X.utils.table_to_sheet(table); | ||||
| 			assert.equal(get_cell(ws, "A1").v, "foo\nbar"); | ||||
| 		}); | ||||
| 		it('should trim whitespace', function() { | ||||
| 			if(get_dom_element("foo <br> bar").innerHTML != "foo <br> bar") return; | ||||
| 			var table = get_dom_element("<table><tr><td>   foo  <br/>  bar   </td><td>  baz  qux  </td></tr></table>"); | ||||
| 			var ws = X.utils.table_to_sheet(table); | ||||
| 			assert.equal(get_cell(ws, "A1").v.replace(/\n/g, "|"), "foo | bar"); | ||||
| 			assert.equal(get_cell(ws, "B1").v, "baz qux"); | ||||
| 		}); | ||||
| 	}); | ||||
| 	if(domtest) it('should handle entities', function() { | ||||
|  | ||||
							
								
								
									
										22
									
								
								tests/core.js
									
									
									
										generated
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										22
									
								
								tests/core.js
									
									
									
										generated
									
									
									
								
							| @ -655,6 +655,7 @@ describe('output formats', function() { | ||||
| 	it('should write binary strings', function() { RT('binary'); }); | ||||
| 	it('should write base64 strings', function() { RT('base64'); }); | ||||
| 	it('should write JS strings', function() { RT('string'); }); | ||||
| 	if(typeof ArrayBuffer !== 'undefined' && (typeof process == 'undefined' || !process.version.match(/v0.12/))) it('should write array buffers', function() { RT('array'); }); | ||||
| 	if(!browser) it('should write buffers', function() { RT('buffer'); }); | ||||
| 	it('should throw if format is unknown', function() { assert.throws(function() { RT('dafuq'); }); }); | ||||
| }); | ||||
| @ -819,10 +820,10 @@ describe('parse features', function() { | ||||
| 		var wbs=[]; | ||||
| 		var bef = (function() { | ||||
| 			wbs = [ | ||||
| 				X.read(fs.readFileSync(paths.cpxlsx), {type:TYPE}), | ||||
| 				X.read(fs.readFileSync(paths.cpxlsb), {type:TYPE}), | ||||
| 				X.read(fs.readFileSync(paths.cpxls), {type:TYPE}), | ||||
| 				X.read(fs.readFileSync(paths.cpxml), {type:TYPE}) | ||||
| 				X.read(fs.readFileSync(paths.cpxlsx), {type:TYPE, WTF:1}), | ||||
| 				X.read(fs.readFileSync(paths.cpxlsb), {type:TYPE, WTF:1}), | ||||
| 				X.read(fs.readFileSync(paths.cpxls), {type:TYPE, WTF:1}), | ||||
| 				X.read(fs.readFileSync(paths.cpxml), {type:TYPE, WTF:1}) | ||||
| 			]; | ||||
| 		}); | ||||
| 		if(typeof before != 'undefined') before(bef); | ||||
| @ -1319,7 +1320,7 @@ describe('roundtrip features', function() { | ||||
| 	}); }); | ||||
| 
 | ||||
| 	describe('should preserve merge cells', function() { | ||||
| 		["xlsx", "xlsb", "xlml", "ods"].forEach(function(f) { it(f, function() { | ||||
| 		["xlsx", "xlsb", "xlml", "ods", "biff8"].forEach(function(f) { it(f, function() { | ||||
| 			var wb1 = X.read(fs.readFileSync(paths.mcxlsx), {type:TYPE}); | ||||
| 			var wb2 = X.read(X.write(wb1,{bookType:f,type:'binary'}),{type:'binary'}); | ||||
| 			var m1 = wb1.Sheets.Merge['!merges'].map(X.utils.encode_range); | ||||
| @ -1911,8 +1912,15 @@ describe('HTML', function() { | ||||
| 		it('should generate strings if raw option is passed', function() { plaintext_test(X.utils.table_to_book(get_dom_element(html_str), {raw:true}), true, true); }); | ||||
| 		it('should handle newlines correctly', function() { | ||||
| 			var table = get_dom_element("<table><tr><td>foo<br/>bar</td><td>baz</td></tr></table>"); | ||||
| 			var wb = X.utils.table_to_book(table); | ||||
| 			assert.equal(get_cell(wb.Sheets.Sheet1, "A1").v, "foo\nbar"); | ||||
| 			var ws = X.utils.table_to_sheet(table); | ||||
| 			assert.equal(get_cell(ws, "A1").v, "foo\nbar"); | ||||
| 		}); | ||||
| 		it('should trim whitespace', function() { | ||||
| 			if(get_dom_element("foo <br> bar").innerHTML != "foo <br> bar") return; | ||||
| 			var table = get_dom_element("<table><tr><td>   foo  <br/>  bar   </td><td>  baz  qux  </td></tr></table>"); | ||||
| 			var ws = X.utils.table_to_sheet(table); | ||||
| 			assert.equal(get_cell(ws, "A1").v.replace(/\n/g, "|"), "foo | bar"); | ||||
| 			assert.equal(get_cell(ws, "B1").v, "baz qux"); | ||||
| 		}); | ||||
| 	}); | ||||
| 	if(domtest) it('should handle entities', function() { | ||||
|  | ||||
| @ -1,6 +1,8 @@ | ||||
| /* writing feature test -- look for TEST: in comments */ | ||||
| /* vim: set ts=2 ft=javascript: */ | ||||
| 
 | ||||
| var ext = !!process.argv[2]; | ||||
| 
 | ||||
| /* original data */ | ||||
| var data = [ | ||||
| 	[1, 2, 3], | ||||
| @ -108,6 +110,9 @@ XLSX.utils.cell_set_number_format(ws['C2'], custfmt); | ||||
| /* TEST: page margins */ | ||||
| ws['!margins'] =  { left:1.0, right:1.0, top:1.0, bottom:1.0, header:0.5, footer:0.5 }; | ||||
| 
 | ||||
| /* TEST: merge cells */ | ||||
| ws['!merges'] = [ XLSX.utils.decode_range("A6:C6") ]; | ||||
| 
 | ||||
| console.log("JSON Data:"); | ||||
| console.log(XLSX.utils.sheet_to_json(ws, {header:1})); | ||||
| 
 | ||||
| @ -158,7 +163,7 @@ ws['!protect'] = { | ||||
| if(!wb.Workbook) wb.Workbook = {Sheets:[], WBProps:{}}; | ||||
| if(!wb.Workbook.WBProps) wb.Workbook.WBProps = {}; | ||||
| wb.Workbook.WBProps.filterPrivacy = true; | ||||
| //wb.Workbook.Views = [{RTL:true}];
 | ||||
| if(ext) wb.Workbook.Views = [{RTL:true}]; | ||||
| 
 | ||||
| console.log("Worksheet Model:"); | ||||
| console.log(ws); | ||||
| @ -167,10 +172,12 @@ var filenames = [ | ||||
| 	['sheetjs.xlsx', {bookSST:true}], | ||||
| 	['sheetjs.xlsm'], | ||||
| 	['sheetjs.xlsb'], | ||||
| 	['sheetjs.xlam'], | ||||
| 	['sheetjs.biff8.xls', {bookType:'xls'}], | ||||
| 	['sheetjs.biff5.xls', {bookType:'biff5'}], | ||||
| 	['sheetjs.biff2.xls', {bookType:'biff2'}], | ||||
| 	['sheetjs.xml.xls', {bookType:'xlml'}], | ||||
| 	['sheetjs.xla'], | ||||
| 	['sheetjs.ods'], | ||||
| 	['sheetjs.fods'], | ||||
| 	['sheetjs.csv'], | ||||
|  | ||||
| @ -19,10 +19,12 @@ program | ||||
| 	.option('-B, --xlsb', 'emit XLSB to <sheetname> or <file>.xlsb') | ||||
| 	.option('-M, --xlsm', 'emit XLSM to <sheetname> or <file>.xlsm') | ||||
| 	.option('-X, --xlsx', 'emit XLSX to <sheetname> or <file>.xlsx') | ||||
| 	.option('-I, --xlam', 'emit XLAM to <sheetname> or <file>.xlam') | ||||
| 	.option('-Y, --ods',  'emit ODS  to <sheetname> or <file>.ods') | ||||
| 	.option('-8, --xls',  'emit XLS  to <sheetname> or <file>.xls (BIFF8)') | ||||
| 	.option('-5, --biff5','emit XLS  to <sheetname> or <file>.xls (BIFF5)') | ||||
| 	.option('-2, --biff2','emit XLS  to <sheetname> or <file>.xls (BIFF2)') | ||||
| 	.option('-i, --xla', 'emit XLA to <sheetname> or <file>.xla') | ||||
| 	.option('-6, --xlml', 'emit SSML to <sheetname> or <file>.xls (2003 XML)') | ||||
| 	.option('-T, --fods', 'emit FODS to <sheetname> or <file>.fods (Flat ODS)') | ||||
| 
 | ||||
| @ -42,6 +44,8 @@ program | ||||
| 	.option('-F, --field-sep <sep>', 'CSV field separator', ",") | ||||
| 	.option('-R, --row-sep <sep>', 'CSV row separator', "\n") | ||||
| 	.option('-n, --sheet-rows <num>', 'Number of rows to process (0=all rows)') | ||||
| 	.option('--codepage <cp>', 'default to specified codepage when ambiguous') | ||||
| 	.option('--req <module>', 'require module before processing') | ||||
| 	.option('--sst', 'generate shared string table for XLS* formats') | ||||
| 	.option('--compress', 'use compression when writing XLSX/M/B and ODS') | ||||
| 	.option('--read', 'read but do not generate output') | ||||
| @ -61,8 +65,10 @@ program.on('--help', function() { | ||||
| const workbook_formats = [ | ||||
| 	['xlsx',   'xlsx', 'xlsx'], | ||||
| 	['xlsm',   'xlsm', 'xlsm'], | ||||
| 	['xlam',   'xlam', 'xlam'], | ||||
| 	['xlsb',   'xlsb', 'xlsb'], | ||||
| 	['xls',     'xls',  'xls'], | ||||
| 	['xla',     'xla',  'xla'], | ||||
| 	['biff5', 'biff5',  'xls'], | ||||
| 	['ods',     'ods',  'ods'], | ||||
| 	['fods',   'fods', 'fods'] | ||||
| @ -126,6 +132,7 @@ if(program.all) { | ||||
| 	wopts.bookVBA = true; | ||||
| } | ||||
| if(program.sparse) opts.dense = false; else opts.dense = true; | ||||
| if(program.codepage) opts.codepage = +program.codepage; | ||||
| 
 | ||||
| if(program.dev) { | ||||
| 	opts.WTF = true; | ||||
|  | ||||
| @ -51,6 +51,8 @@ read_opts.type = "buffer"; | ||||
| const wb3 = XLSX.read(fs.readFileSync("sheetjs.xlsx"), read_opts); | ||||
| write_opts.type = "base64"; | ||||
| const out3 = XLSX.write(wb3, write_opts); | ||||
| write_opts.type = "array"; | ||||
| const out4 = XLSX.write(wb3, write_opts); | ||||
| 
 | ||||
| const ws1 = XLSX.utils.aoa_to_sheet([ | ||||
|     "SheetJS".split(""), | ||||
|  | ||||
							
								
								
									
										15
									
								
								types/index.d.ts
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										15
									
								
								types/index.d.ts
									
									
									
									
										vendored
									
									
								
							| @ -110,6 +110,9 @@ export interface ParsingOptions extends CommonOptions { | ||||
|     /** Input data encoding */ | ||||
|     type?: 'base64' | 'binary' | 'buffer' | 'file' | 'array'; | ||||
| 
 | ||||
|     /** Default codepage */ | ||||
|     codepage?: number; | ||||
| 
 | ||||
|     /** | ||||
|      * Save formulae to the .f field | ||||
|      * @default true | ||||
| @ -188,7 +191,7 @@ export interface ParsingOptions extends CommonOptions { | ||||
| /** Options for write and writeFile */ | ||||
| export interface WritingOptions extends CommonOptions { | ||||
|     /** Output data encoding */ | ||||
|     type?: 'base64' | 'binary' | 'buffer' | 'file'; | ||||
|     type?: 'base64' | 'binary' | 'buffer' | 'file' | 'array'; | ||||
| 
 | ||||
|     /** | ||||
|      * Generate Shared String Table | ||||
| @ -272,12 +275,18 @@ export interface WBProps { | ||||
|     Names?: DefinedName[]; | ||||
| 
 | ||||
|     /** Workbook Views */ | ||||
|     Views?: any[]; | ||||
|     Views?: WBView[]; | ||||
| 
 | ||||
|     /** Other Workbook Properties */ | ||||
|     WBProps?: WorkbookProperties; | ||||
| } | ||||
| 
 | ||||
| /** Workbook View */ | ||||
| export interface WBView { | ||||
|     /** Right-to-left mode */ | ||||
|     RTL?: boolean; | ||||
| } | ||||
| 
 | ||||
| /** Other Workbook Properties */ | ||||
| export interface WorkbookProperties { | ||||
|     /** Worksheet Epoch (1904 if true, 1900 if false) */ | ||||
| @ -493,7 +502,7 @@ export type ExcelDataType = 'b' | 'n' | 'e' | 's' | 'd' | 'z'; | ||||
|  * Type of generated workbook | ||||
|  * @default 'xlsx' | ||||
|  */ | ||||
| export type BookType = 'xlsx' | 'xlsm' | 'xlsb' | 'xls' | 'biff8' | 'biff5' | 'biff2' | 'xlml' | 'ods' | 'fods' | 'csv' | 'txt' | 'sylk' | 'html' | 'dif' | 'rtf' | 'prn' | 'eth'; | ||||
| export type BookType = 'xlsx' | 'xlsm' | 'xlsb' | 'xls' | 'xla' | 'biff8' | 'biff5' | 'biff2' | 'xlml' | 'ods' | 'fods' | 'csv' | 'txt' | 'sylk' | 'html' | 'dif' | 'rtf' | 'prn' | 'eth'; | ||||
| 
 | ||||
| /** Comment element */ | ||||
| export interface Comment { | ||||
|  | ||||
| @ -96,6 +96,9 @@ XLSX.utils.cell_set_number_format(ws['C2'], custfmt); | ||||
| /* TEST: page margins */ | ||||
| ws['!margins'] =  { left:1.0, right:1.0, top:1.0, bottom:1.0, header:0.5, footer:0.5 }; | ||||
| 
 | ||||
| /* TEST: merge cells */ | ||||
| ws['!merges'] = [ XLSX.utils.decode_range("A6:C6") ]; | ||||
| 
 | ||||
| console.log("JSON Data:"); | ||||
| console.log(XLSX.utils.sheet_to_json(ws, {header:1})); | ||||
| 
 | ||||
| @ -153,10 +156,12 @@ const filenames: Array<[string]|[string, XLSX.WritingOptions]> = [ | ||||
| 	['sheetjs.xlsx', {bookSST:true}], | ||||
| 	['sheetjs.xlsm'], | ||||
| 	['sheetjs.xlsb'], | ||||
| 	['sheetjs.xlam'], | ||||
| 	['sheetjs.biff8.xls', {bookType:'xls'}], | ||||
| 	['sheetjs.biff5.xls', {bookType:'biff5'}], | ||||
| 	['sheetjs.biff2.xls', {bookType:'biff2'}], | ||||
| 	['sheetjs.xml.xls', {bookType:'xlml'}], | ||||
| 	['sheetjs.xla'], | ||||
| 	['sheetjs.ods'], | ||||
| 	['sheetjs.fods'], | ||||
| 	['sheetjs.csv'], | ||||
|  | ||||
							
								
								
									
										859
									
								
								xlsx.flow.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										859
									
								
								xlsx.flow.js
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Loading…
	
		Reference in New Issue
	
	Block a user