forked from sheetjs/sheetjs
		
	Formula write support
- XLSX/XLML/ODS/CSV formula write - XLS Array/Formula record parsing - ODS to/from CSF formula conversion - XLML parse negative dates - formula multiformat and roundtrip tests - update SSF Closes issues: - closes #549 h/t @omershelef - closes #306 h/t @akaustel - closes #300 h/t @wawanopoulos - closes #152 h/t @florf - closes #103 h/t @christocracy - closes #112 h/t @johnyesberg - closes #307 h/t @alexanderknapstein
This commit is contained in:
		
							parent
							
								
									ea1873e572
								
							
						
					
					
						commit
						5a3774e36e
					
				| @ -484,7 +484,7 @@ will not be generated; the parser `sheetStubs` option must be set to `true`. | ||||
| ### Formulae | ||||
| 
 | ||||
| The A1-style formula string is stored in the `f` field.  Even though different | ||||
| file formats store the formulae in different ways, the formats are converted. | ||||
| file formats store the formulae in different ways, the formats are translated. | ||||
| 
 | ||||
| Shared formulae are decompressed and each cell has the correct formula. | ||||
| 
 | ||||
|  | ||||
| @ -310,7 +310,18 @@ function hashq(str/*:string*/)/*:string*/ { | ||||
| 	return o; | ||||
| } | ||||
| function rnd(val/*:number*/, d/*:number*/)/*:string*/ { var dd = Math.pow(10,d); return ""+(Math.round(val * dd)/dd); } | ||||
| function dec(val/*:number*/, d/*:number*/)/*:number*/ { return Math.round((val-Math.floor(val))*Math.pow(10,d)); } | ||||
| function dec(val/*:number*/, d/*:number*/)/*:number*/ { | ||||
| 	if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) { | ||||
| 		return 0; | ||||
| 	} | ||||
| 	return Math.round((val-Math.floor(val))*Math.pow(10,d)); | ||||
| } | ||||
| function carry(val/*:number*/, d/*:number*/)/*:number*/ { | ||||
| 	if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) { | ||||
| 		return 1; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| function flr(val/*:number*/)/*:string*/ { if(val < 2147483647 && val > -2147483648) return ""+(val >= 0 ? (val|0) : (val-1|0)); return ""+Math.floor(val); } | ||||
| function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/ { | ||||
| 	if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) { | ||||
| @ -332,8 +343,7 @@ function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string | ||||
| 	if((r = fmt.match(frac1))) return write_num_f1(r, aval, sign); | ||||
| 	if(fmt.match(/^#+0+$/)) return sign + pad0r(aval,fmt.length - fmt.indexOf("0")); | ||||
| 	if((r = fmt.match(dec1))) { | ||||
| 		// $FlowIgnore
 | ||||
| 		o = rnd(val, r[1].length).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.(\d*)$/,function($$, $1) { return "." + $1 + fill("0", r[1].length-$1.length); }); | ||||
| 		o = rnd(val, r[1].length).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.(\d*)$/,function($$, $1) { return "." + $1 + fill("0", /*::(*/r/*::||[""])*/[1].length-$1.length); }); | ||||
| 		return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,"."); | ||||
| 	} | ||||
| 	fmt = fmt.replace(/^#+([0.])/, "$1"); | ||||
| @ -342,7 +352,7 @@ function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string | ||||
| 	} | ||||
| 	if((r = fmt.match(/^#,##0(\.?)$/))) return sign + commaify(pad0r(aval,0)); | ||||
| 	if((r = fmt.match(/^#,##0\.([#0]*0)$/))) { | ||||
| 		return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(""+(Math.floor(val))) + "." + pad0(dec(val, r[1].length),r[1].length); | ||||
| 		return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(""+(Math.floor(val) + carry(val, r[1].length))) + "." + pad0(dec(val, r[1].length),r[1].length); | ||||
| 	} | ||||
| 	if((r = fmt.match(/^#,#*,#0/))) return write_num_flt(type,fmt.replace(/^#,#*,/,""),val); | ||||
| 	if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) { | ||||
|  | ||||
| @ -6,6 +6,16 @@ function ods_to_csf_formula(f/*:string*/)/*:string*/ { | ||||
| 		f = f.substr(1); | ||||
| 		if(f.charCodeAt(0) == 61) f = f.substr(1); | ||||
| 	} | ||||
| 	f = f.replace(/COM\.MICROSOFT\./g, ""); | ||||
| 	/* Part 3 Section 5.8 References */ | ||||
| 	return f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, "$1").replace(/\./g, ""); | ||||
| 	f = f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, function($$, $1) { return $1.replace(/\./g,""); }); | ||||
| 	/* TODO: something other than this */ | ||||
| 	f = f.replace(/\[.(#[A-Z]*[?!])\]/g, "$1"); | ||||
| 	return f.replace(/[;~]/g,",").replace(/\|/g,";"); | ||||
| } | ||||
| 
 | ||||
| function csf_to_ods_formula(f/*:string*/)/*:string*/ { | ||||
| 	var o = "of:=" + f.replace(crefregex, "$1[.$2$3$4$5]").replace(/\]:\[/g,":"); | ||||
| 	/* TODO: something other than this */ | ||||
| 	return o.replace(/;/g, "|").replace(/,/g,";"); | ||||
| } | ||||
|  | ||||
| @ -126,7 +126,7 @@ function write_ws_xml_cols(ws, cols)/*:string*/ { | ||||
| } | ||||
| 
 | ||||
| function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) { | ||||
| 	if(cell.v === undefined || cell.t === 'z') return ""; | ||||
| 	if(cell.v === undefined && cell.f === undefined || cell.t === 'z') return ""; | ||||
| 	var vv = ""; | ||||
| 	var oldt = cell.t, oldv = cell.v; | ||||
| 	switch(cell.t) { | ||||
| @ -152,7 +152,7 @@ function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) { | ||||
| 		case 'd': o.t = "d"; break; | ||||
| 		case 'b': o.t = "b"; break; | ||||
| 		case 'e': o.t = "e"; break; | ||||
| 		default: | ||||
| 		default: if(cell.v == null) { delete cell.t; break; } | ||||
| 			if(opts.bookSST) { | ||||
| 				v = writetag('v', ''+get_sst_id(opts.Strings, cell.v)); | ||||
| 				o.t = "s"; break; | ||||
| @ -160,6 +160,10 @@ function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) { | ||||
| 			o.t = "str"; break; | ||||
| 	} | ||||
| 	if(cell.t != oldt) { cell.t = oldt; cell.v = oldv; } | ||||
| 	if(cell.f) { | ||||
| 		var ff = cell.F && cell.F.substr(0, ref.length) == ref ? {t:"array", ref:cell.F} : null; | ||||
| 		v = writextag('f', escapexml(cell.f), ff) + (cell.v != null ? v : ""); | ||||
| 	} | ||||
| 	return writextag('c', v, o); | ||||
| } | ||||
| 
 | ||||
| @ -215,7 +219,8 @@ return function parse_ws_xml_data(sdata, s, opts, guess) { | ||||
| 			if((cref=d.match(match_v))!= null && /*::cref != null && */cref[1] !== '') p.v=unescapexml(cref[1]); | ||||
| 			if(opts.cellFormula) { | ||||
| 				if((cref=d.match(match_f))!= null && /*::cref != null && */cref[1] !== '') { | ||||
| 					p.f=unescapexml(utf8read(cref[1])); | ||||
| 					/* TODO: match against XLSXFutureFunctions */ | ||||
| 					p.f=unescapexml(utf8read(cref[1])).replace(/_xlfn\./,""); | ||||
| 					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]); | ||||
|  | ||||
| @ -108,7 +108,7 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, a | ||||
| 		case 'DateTime': | ||||
| 			cell.v = (Date.parse(xml) - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000); | ||||
| 			if(cell.v !== cell.v) cell.v = unescapexml(xml); | ||||
| 			else if(cell.v >= 1 && cell.v<60) cell.v = cell.v -1; | ||||
| 			else if(cell.v<60) cell.v = cell.v -1; | ||||
| 			if(!nf || nf == "General") nf = "yyyy-mm-dd"; | ||||
| 			/* falls through */ | ||||
| 		case 'Number': | ||||
| @ -250,6 +250,7 @@ function parse_xlml_xml(d, opts)/*:Workbook*/ { | ||||
| 				sheetname = unescapexml(tmp.Name); | ||||
| 				cursheet = {}; | ||||
| 				mergecells = []; | ||||
| 				arrayf = []; | ||||
| 			} | ||||
| 			break; | ||||
| 		case 'Table': | ||||
| @ -759,10 +760,14 @@ function write_sty_xlml(wb, opts)/*:string*/ { | ||||
| } | ||||
| /* TODO */ | ||||
| function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr)/*:string*/{ | ||||
| 	if(!cell || cell.v === undefined) return "<Cell></Cell>"; | ||||
| 	if(!cell || cell.v == undefined && cell.f == undefined) return "<Cell></Cell>"; | ||||
| 
 | ||||
| 	var attr = {}; | ||||
| 	if(cell.f) attr["ss:Formula"] = "=" + escapexml(a1_to_rc(cell.f, addr)); | ||||
| 	if(cell.F && cell.F.substr(0, ref.length) == ref) { | ||||
| 		var end = decode_cell(cell.F.substr(ref.length + 1)); | ||||
| 		attr["ss:ArrayRange"] = "RC:R" + (end.r == addr.r ? "" : "[" + (end.r - addr.r) + "]") + "C" + (end.c == addr.c ? "" : "[" + (end.c - addr.c) + "]"); | ||||
| 	} | ||||
| 
 | ||||
| 	if(ws['!merges']) { | ||||
| 		var marr = ws['!merges']; | ||||
| @ -780,9 +785,9 @@ function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr)/*:string*/{ | ||||
| 		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 's':  t = 'String'; p = escapexml(cell.v||""); break; | ||||
| 		case 's': t = 'String'; p = escapexml(cell.v||""); break; | ||||
| 	} | ||||
| 	var m = '<Data ss:Type="' + t + '">' + p + '</Data>'; | ||||
| 	var m = '<Data ss:Type="' + t + '">' + (cell.v != null ? p : "") + '</Data>'; | ||||
| 
 | ||||
| 	return writextag("Cell", m, attr); | ||||
| } | ||||
|  | ||||
| @ -122,6 +122,19 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 			if(cell.r + 1 > range.e.r) range.e.r = cell.r + 1; | ||||
| 			if(cell.c + 1 > range.e.c) range.e.c = cell.c + 1; | ||||
| 		} | ||||
| 		if(options.cellFormula && line.f) { | ||||
| 			for(var afi = 0; afi < 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); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		if(options.sheetRows && lastcell.r >= options.sheetRows) cell_valid = false; | ||||
| 		else out[last_cell] = line; | ||||
| 	}; | ||||
| @ -274,7 +287,9 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 					else cur_sheet = (Directory[s] || {name:""}).name; | ||||
| 					mergecells = []; | ||||
| 					objects = []; | ||||
| 					array_formulae = []; opts.arrayf = array_formulae; | ||||
| 				} break; | ||||
| 
 | ||||
| 				case 'Number': case 'BIFF2NUM': case 'BIFF2INT': { | ||||
| 					temp_val = {ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:'n'}; | ||||
| 					safe_format_xf(temp_val, options, wb.opts.Date1904); | ||||
| @ -299,44 +314,43 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 					} | ||||
| 				} break; | ||||
| 				case 'Formula': { | ||||
| 					switch(val.val) { | ||||
| 						case 'String': last_formula = val; break; | ||||
| 						case 'Array Formula': throw "Array Formula unsupported"; | ||||
| 						default: | ||||
| 							temp_val = ({v:val.val, ixfe:val.cell.ixfe, t:val.tt}/*:any*/); | ||||
| 							temp_val.XF = XFs[temp_val.ixfe]; | ||||
| 							if(options.cellFormula) { | ||||
| 								var _f = val.formula; | ||||
| 								if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') { | ||||
| 									var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1]; | ||||
| 									var _fe = encode_cell({r:_fr, c:_fc}); | ||||
| 									if(shared_formulae[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); | ||||
| 									else temp_val.F = (out[_fe] || {}).F; | ||||
| 								} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); | ||||
| 							} | ||||
| 							safe_format_xf(temp_val, options, wb.opts.Date1904); | ||||
| 							addcell(val.cell, temp_val, options); | ||||
| 							last_formula = val; | ||||
| 					if(val.val == 'String') { last_formula = val; break; } | ||||
| 					temp_val = ({v:val.val, ixfe:val.cell.ixfe, t:val.tt}/*:any*/); | ||||
| 					temp_val.XF = XFs[temp_val.ixfe]; | ||||
| 					if(options.cellFormula) { | ||||
| 						var _f = val.formula; | ||||
| 						if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') { | ||||
| 							var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1]; | ||||
| 							var _fe = encode_cell({r:_fr, c:_fc}); | ||||
| 							if(shared_formulae[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); | ||||
| 							else temp_val.F = (out[_fe] || {}).F; | ||||
| 						} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); | ||||
| 					} | ||||
| 					safe_format_xf(temp_val, options, wb.opts.Date1904); | ||||
| 					addcell(val.cell, temp_val, options); | ||||
| 					last_formula = val; | ||||
| 				} break; | ||||
| 				case 'String': { | ||||
| 					if(last_formula) { | ||||
| 					if(last_formula) { /* technically always true */ | ||||
| 						last_formula.val = val; | ||||
| 						temp_val = ({v:last_formula.val, ixfe:last_formula.cell.ixfe, t:'s'}/*:any*/); | ||||
| 						temp_val = ({v:val, ixfe:last_formula.cell.ixfe, t:'s'}/*:any*/); | ||||
| 						temp_val.XF = XFs[temp_val.ixfe]; | ||||
| 						if(options.cellFormula) temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts); | ||||
| 						if(options.cellFormula) { | ||||
| 							temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts); | ||||
| 						} | ||||
| 						safe_format_xf(temp_val, options, wb.opts.Date1904); | ||||
| 						addcell(last_formula.cell, temp_val, options); | ||||
| 						last_formula = null; | ||||
| 					} | ||||
| 					} else throw new Error("String record expects Formula"); | ||||
| 				} break; | ||||
| 				case 'Array': { | ||||
| 					array_formulae.push(val); | ||||
| 					if(options.cellFormula && out[last_cell]) { | ||||
| 					var _arraystart = encode_cell(val[0].s); | ||||
| 					if(options.cellFormula && out[_arraystart]) { | ||||
| 						if(!last_formula) break; /* technically unreachable */ | ||||
| 						if(!last_cell || !out[last_cell]) break; /* technically unreachable */ | ||||
| 						out[last_cell].f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts); | ||||
| 						out[last_cell].F = encode_range(val[0]); | ||||
| 						if(!_arraystart || !out[_arraystart]) break; | ||||
| 						out[_arraystart].f = ""+stringify_formula(val[1], range, val[0], supbooks, opts); | ||||
| 						out[_arraystart].F = encode_range(val[0]); | ||||
| 					} | ||||
| 				} break; | ||||
| 				case 'ShrFmla': { | ||||
| @ -375,6 +389,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 					safe_format_xf(temp_val, options, wb.opts.Date1904); | ||||
| 					addcell({c:val.c, r:val.r}, temp_val, options); | ||||
| 					break; | ||||
| 
 | ||||
| 				case 'Dimensions': { | ||||
| 					if(file_depth === 1) range = val; /* TODO: stack */ | ||||
| 				} break; | ||||
|  | ||||
| @ -57,20 +57,20 @@ function write_BIFF2LABEL(r, c, val) { | ||||
| } | ||||
| 
 | ||||
| function write_ws_biff_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts) { | ||||
| 	switch(cell.t) { | ||||
| 	if(cell.v != null) switch(cell.t) { | ||||
| 		case 'n': | ||||
| 			if((cell.v == (cell.v|0)) && (cell.v >= 0) && (cell.v < 65536)) | ||||
| 				write_biff_rec(ba, 0x0002, write_BIFF2INT(R, C, cell.v)); | ||||
| 			else | ||||
| 				write_biff_rec(ba, 0x0003, write_BIFF2NUMBER(R,C, cell.v)); | ||||
| 			break; | ||||
| 		case 'b': case 'e': write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); break; | ||||
| 			return; | ||||
| 		case 'b': case 'e': write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); return; | ||||
| 		/* TODO: codepage, sst */ | ||||
| 		case 's': case 'str': | ||||
| 			write_biff_rec(ba, 0x0004, write_BIFF2LABEL(R, C, cell.v)); | ||||
| 			break; | ||||
| 		default: write_biff_rec(ba, 0x0001, write_BIFF2Cell(null, R, C)); | ||||
| 			return; | ||||
| 	} | ||||
| 	write_biff_rec(ba, 0x0001, write_BIFF2Cell(null, R, C)); | ||||
| } | ||||
| 
 | ||||
| function write_biff_ws(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbook*/) { | ||||
|  | ||||
| @ -78,6 +78,7 @@ var parse_content_xml = (function() { | ||||
| 					ctag = parsexmltag(Rn[0], false); | ||||
| 					q = ({t:ctag['数据类型'] || ctag['value-type'], v:null/*:: , z:null, w:""*/}/*:any*/); | ||||
| 					if(opts.cellFormula) { | ||||
| 						if(ctag.formula) ctag.formula = unescapexml(ctag.formula); | ||||
| 						if(ctag['number-matrix-columns-spanned'] && ctag['number-matrix-rows-spanned']) { | ||||
| 							mR = parseInt(ctag['number-matrix-rows-spanned'],10) || 0; | ||||
| 							mC = parseInt(ctag['number-matrix-columns-spanned'],10) || 0; | ||||
|  | ||||
| @ -27,11 +27,22 @@ var write_content_xml/*:{(wb:any, opts:any):string}*/ = (function() { | ||||
| 				} | ||||
| 				if(skip) { o.push(covered_cell_xml); continue; } | ||||
| 				var ref = encode_cell({r:R, c:C}), cell = ws[ref]; | ||||
| 				var fmla = ""; | ||||
| 				if(cell && cell.f) { | ||||
| 					fmla = ' table:formula="' + escapexml(csf_to_ods_formula(cell.f)) + '"'; | ||||
| 					if(cell.F) { | ||||
| 						if(cell.F.substr(0, ref.length) == ref) { | ||||
| 							var _Fref = decode_range(cell.F); | ||||
| 							fmla += ' table:number-matrix-columns-spanned="' + (_Fref.e.c - _Fref.s.c + 1)+ '"'; | ||||
| 							fmla += ' table:number-matrix-rows-spanned="' + (_Fref.e.r - _Fref.s.r + 1) + '"'; | ||||
| 						} else fmla = ""; | ||||
| 					} | ||||
| 				} | ||||
| 				if(cell) switch(cell.t) { | ||||
| 					case 'b': o.push(cell_begin + mxml + vt + '"boolean" office:boolean-value="' + (cell.v ? 'true' : 'false') + '">' + p_begin + (cell.v ? 'TRUE' : 'FALSE') + p_end + cell_end); break; | ||||
| 					case 'n': o.push(cell_begin + mxml + vt + '"float" office:value="' + cell.v + '">' + p_begin + (cell.w||cell.v) + p_end + cell_end); break; | ||||
| 					case 's': case 'str': o.push(cell_begin + mxml + vt + '"string">' + p_begin + escapexml(cell.v) + p_end + cell_end); break; | ||||
| 					case 'd': o.push(cell_begin + mxml + vt + '"date" office:date-value="' + (new Date(cell.v).toISOString()) + '">' + p_begin + (cell.w||(new Date(cell.v).toISOString())) + p_end + cell_end); break; | ||||
| 					case 'b': o.push(cell_begin + mxml + vt + '"boolean" office:boolean-value="' + (cell.v ? 'true' : 'false') + '"' + fmla + '>' + p_begin + (cell.v ? 'TRUE' : 'FALSE') + p_end + cell_end); break; | ||||
| 					case 'n': o.push(cell_begin + mxml + vt + '"float" office:value="' + cell.v + '"' + fmla + '>' + p_begin + (cell.w||cell.v) + p_end + cell_end); break; | ||||
| 					case 's': case 'str': o.push(cell_begin + mxml + vt + '"string"' + fmla + '>' + p_begin + escapexml(cell.v) + p_end + cell_end); break; | ||||
| 					case 'd': o.push(cell_begin + mxml + vt + '"date" office:date-value="' + (new Date(cell.v).toISOString()) + '"' + fmla + '>' + p_begin + (cell.w||(new Date(cell.v).toISOString())) + p_end + cell_end); break; | ||||
| 					//case 'e':
 | ||||
| 					default: o.push(null_cell_xml); | ||||
| 				} else o.push(null_cell_xml); | ||||
| @ -46,7 +57,7 @@ var write_content_xml/*:{(wb:any, opts:any):string}*/ = (function() { | ||||
| 		var o = [XML_HEADER]; | ||||
| 		/* 3.1.3.2 */ | ||||
| 		if(opts.bookType == "fods") o.push('<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.spreadsheet">'); | ||||
| 		else o.push('<office:document-content office:version="1.2" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0">\n'); // TODO
 | ||||
| 		else o.push('<office:document-content office:version="1.2" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2">\n'); // TODO
 | ||||
| 		o.push('  <office:body>\n'); | ||||
| 		o.push('    <office:spreadsheet>\n'); | ||||
| 		for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts)); | ||||
|  | ||||
| @ -156,9 +156,15 @@ function sheet_to_csv(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) { | ||||
| 		rr = encode_row(R); | ||||
| 		for(C = r.s.c; C <= r.e.c; ++C) { | ||||
| 			val = sheet[cols[C] + rr]; | ||||
| 			txt = val !== undefined ? ''+format_cell(val) : ""; | ||||
| 			for(i = 0, cc = 0; i !== txt.length; ++i) if((cc = txt.charCodeAt(i)) === fs || cc === rs || cc === 34) { | ||||
| 				txt = "\"" + txt.replace(qreg, '""') + "\""; break; } | ||||
| 			if(val == null) txt = ""; | ||||
| 			else if(val.v != null) { | ||||
| 				txt = ''+format_cell(val); | ||||
| 				for(i = 0, cc = 0; i !== txt.length; ++i) if((cc = txt.charCodeAt(i)) === fs || cc === rs || cc === 34) { | ||||
| 					txt = "\"" + txt.replace(qreg, '""') + "\""; break; } | ||||
| 			} else if(val.f != null && !val.F) { | ||||
| 				txt = '=' + val.f; if(txt.indexOf(",") >= 0) txt = '"' + txt.replace(qreg, '""') + '"'; | ||||
| 			} else txt = ""; | ||||
| 			/* NOTE: Excel CSV does not support array formulae */ | ||||
| 			row += (C === r.s.c ? "" : FS) + txt; | ||||
| 		} | ||||
| 		out += row + RS; | ||||
|  | ||||
| @ -10,13 +10,19 @@ cell_style_simple       	.xls .xlsb .xlsx .xml | ||||
| comments_stress_test    	.xls .xlsb .xlsx .xls.xml .xlsb.xml .xlsx.xml | ||||
| # yes-csv | ||||
| custom_properties       	.xls .xlsb .xlsx .xls.xml .xlsb.xml .xlsx.xml | ||||
| # no-formula (defined names) | ||||
| defined_names_simple    	.xls .xlsb .xlsx .xml | ||||
| #formula_stress_test     	.xls .xlsb .xlsx .xls.xml .xlsb.xml .xlsx.xml | ||||
| # yes-formula | ||||
| # no-csv (randbetween) note: ODS does not support many XLSX functions  | ||||
| formula_stress_test     	.xls .xlsb .xlsx .xls.xml .xlsb.xml .xlsx.xml | ||||
| # yes-csv | ||||
| formulae_test_simple    	.xls .xlsb .xlsx .xml | ||||
| hyperlink_stress_test_2011	.xls .xlsb .xlsx .xml | ||||
| #large_strings           	.xls .xlsb .xlsx .xls.xml .xlsb.xml .xlsx.xml | ||||
| merge_cells             	.xls .xlsb .xlsx .xls.xml .xlsb.xml .xlsx.xml | ||||
| # no-formula (defined names) | ||||
| named_ranges_2011       	.xls .xlsb .xlsx .xls.xml .xlsb.xml .xlsx.xml | ||||
| # yes-formula | ||||
| # no-csv (macro serialization in xml) | ||||
| number_format           	.xls .xlsb .xlsm .xls.xml .xlsb.xml .xlsm.xml | ||||
| number_format_entities  	.xls .xlsb .xlsx .xml | ||||
|  | ||||
							
								
								
									
										34
									
								
								test.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										34
									
								
								test.js
									
									
									
									
									
								
							| @ -838,9 +838,7 @@ function seq(end, start) { | ||||
| } | ||||
| 
 | ||||
| describe('roundtrip features', function() { | ||||
| 	var bef = (function() { | ||||
| 		X = require(modp); | ||||
| 	}); | ||||
| 	var bef = (function() { X = require(modp); }); | ||||
| 	if(typeof before != 'undefined') before(bef); | ||||
| 	else it('before', bef); | ||||
| 	describe('should parse core properties and custom properties', function() { | ||||
| @ -907,14 +905,18 @@ describe('roundtrip features', function() { | ||||
| 		}); | ||||
| 	}); | ||||
| 
 | ||||
| 	describe('xls to xlsx conversions', function() { [ | ||||
| 			['XLS', 'formula_stress_test.xls'], | ||||
| 			['XML', 'formula_stress_test.xls.xml'] | ||||
| 	describe('should preserve formulae', function() { [ | ||||
| 			['xlml', paths.fstxml], | ||||
| 			['xlsx', paths.fstxlsx], | ||||
| 			['ods',  paths.fstods] | ||||
| 		].forEach(function(w) { | ||||
| 			it('should be able to write ' + w[0] + ' files', function() { | ||||
| 				var xls = X.readFile('./test_files/' + w[1], {cellNF:true}); | ||||
| 				X.writeFile(xls, './tmp/' + w[1] + '.xlsx', {bookSST:true}); | ||||
| 				X.writeFile(xls, './tmp/' + w[1] + '.xlsb', {bookSST:true}); | ||||
| 			it(w[0], function() { | ||||
| 				var wb1 = X.readFile(w[1], {cellFormula:true}); | ||||
| 				if(w[0] == 'ods') X.writeFile(wb1, "./tmp/_.ods", {bookType:"ods"}); | ||||
| 				var wb2 = X.read(X.write(wb1, {bookType:w[0], type:"buffer"}), {cellFormula:true, type:"buffer"}); | ||||
| 				wb1.SheetNames.forEach(function(n) { | ||||
| 					assert.equal( X.utils.sheet_to_formulae(wb1.Sheets[n]).sort().join("\n"), X.utils.sheet_to_formulae(wb2.Sheets[n]).sort().join("\n") ); | ||||
| 				}); | ||||
| 			}); | ||||
| 		}); | ||||
| 	}); | ||||
| @ -1209,7 +1211,7 @@ describe('encryption', function() { | ||||
| describe('multiformat tests', function() { | ||||
| var mfopts = opts; | ||||
| var mft = fs.readFileSync('multiformat.lst','utf-8').split("\n"); | ||||
| var csv = true; | ||||
| var csv = true, formulae = false; | ||||
| mft.forEach(function(x) { | ||||
| 	if(x[0]!="#") describe('MFT ' + x, function() { | ||||
| 		var fil = {}, f = [], r = x.split(/\s+/); | ||||
| @ -1239,10 +1241,20 @@ mft.forEach(function(x) { | ||||
| 				cmparr(f.map(function(x) { return X.utils.sheet_to_csv(x.Sheets[name]); })); | ||||
| 			}); | ||||
| 		} : null); | ||||
| 		it('should have the same formulae', formulae ? function() { | ||||
| 			cmparr(f.map(function(x) { return x.SheetNames; })); | ||||
| 			var names = f[0].SheetNames; | ||||
| 			names.forEach(function(name) { | ||||
| 				cmparr(f.map(function(x) { return X.utils.sheet_to_formulae(x.Sheets[name]).sort(); })); | ||||
| 			}); | ||||
| 		} : null); | ||||
| 
 | ||||
| 	}); | ||||
| 	else x.split(/\s+/).forEach(function(w) { switch(w) { | ||||
| 		case "no-csv": csv = false; break; | ||||
| 		case "yes-csv": csv = true; break; | ||||
| 		case "no-formula": formulae = false; break; | ||||
| 		case "yes-formula": formulae = true; break; | ||||
| 	}}); | ||||
| }); | ||||
| }); | ||||
|  | ||||
| @ -1 +1 @@ | ||||
| Subproject commit 8ab3308622f83ac47a0ee584d61e11357b01f925 | ||||
| Subproject commit e0b7060b10ef972ad48869faa4efffd089e1a428 | ||||
							
								
								
									
										245
									
								
								tests.lst
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										245
									
								
								tests.lst
									
									
									
									
									
								
							| @ -29,17 +29,6 @@ sushi.xlsb | ||||
| text_and_numbers.xlsb | ||||
| time_stress_test_1.xlsb.pending | ||||
| xlsx-stream-d-date-cell.xlsb | ||||
| 2013/apachepoi_29982.xls.xlsb | ||||
| 2013/apachepoi_43251.xls.xlsb | ||||
| 2013/apachepoi_44593.xls.xlsb ## xlsb loop timeout | ||||
| 2013/apachepoi_44643.xls.xlsb | ||||
| 2013/apachepoi_44958.xls.xlsb | ||||
| 2013/apachepoi_46136-NoWarnings.xls.xlsb | ||||
| 2013/apachepoi_48968.xls.xlsb | ||||
| 2013/apachepoi_50939.xls.xlsb | ||||
| 2013/apachepoi_54016.xls.xlsb | ||||
| 2013/apachepoi_ReadOnlyRecommended.xls.xlsb | ||||
| 2013/apachepoi_testArraysAndTables.xls.xlsb | ||||
| AutoFilter.xlsx | ||||
| ErrorTypes.xlsx | ||||
| LONumbers-2010.xlsx | ||||
| @ -199,6 +188,7 @@ apachepoi_DataTableCities.xlsx | ||||
| apachepoi_DataValidationEvaluations.xlsx | ||||
| apachepoi_DataValidations-49244.xlsx | ||||
| # apachepoi_DateFormatTests.xlsx # xlml | ||||
| apachepoi_DateFormatTests.xlsx.xlsx | ||||
| apachepoi_ElapsedFormatTests.xlsx | ||||
| apachepoi_ExcelTables.xlsx | ||||
| apachepoi_ForShifting.xlsx | ||||
| @ -249,6 +239,7 @@ apachepoi_WithTwoCharts.xlsx | ||||
| apachepoi_WithVariousData.xlsx | ||||
| apachepoi_XSSFSheet.copyRows.xlsx | ||||
| apachepoi_atp.xlsx | ||||
| apachepoi_bug60858.xlsx | ||||
| apachepoi_chartTitle_noTitle.xlsx | ||||
| apachepoi_chartTitle_withTitle.xlsx | ||||
| apachepoi_chart_sheet.xlsx.pending | ||||
| @ -362,6 +353,8 @@ openpyxl_r_null_file.xlsx.pending | ||||
| phonetic_text.xlsx | ||||
| pivot_table_named_range.xlsx | ||||
| rich_text_stress.xlsx | ||||
| roo-xls_numbers1.xlsx | ||||
| roo-xls_type_excel.xlsx | ||||
| roo_1900_base.xlsx | ||||
| roo_1904_base.xlsx | ||||
| roo_Bibelbund.xlsx | ||||
| @ -404,6 +397,44 @@ roo_whitespace.xlsx | ||||
| roo_x000D.xlsx | ||||
| roo_zero-padded-number.xlsx | ||||
| smart_tags_2007.xlsx | ||||
| spout-xlsx_attack_billion_laughs.xlsx | ||||
| spout-xlsx_attack_quadratic_blowup.xlsx | ||||
| # spout-xlsx_file_corrupted.xlsx | ||||
| spout-xlsx_file_with_no_sheets_in_workbook_xml.xlsx | ||||
| # spout-xlsx_file_with_sheet_xml_not_matching_content_types.xlsx | ||||
| spout-xlsx_one_sheet_with_inline_strings.xlsx | ||||
| spout-xlsx_one_sheet_with_invalid_xml_characters.xlsx | ||||
| spout-xlsx_one_sheet_with_shared_multiline_strings.xlsx | ||||
| spout-xlsx_one_sheet_with_shared_strings.xlsx | ||||
| spout-xlsx_one_sheet_with_shared_strings_containing_text_and_hyperlink_in_same_cell.xlsx | ||||
| spout-xlsx_one_sheet_with_shared_strings_missing_unique_count.xlsx | ||||
| spout-xlsx_one_sheet_with_shared_strings_missing_unique_count_and_count.xlsx | ||||
| spout-xlsx_sheet_with_all_cell_types.xlsx | ||||
| spout-xlsx_sheet_with_custom_date_formats_and_no_apply_number_format.xlsx | ||||
| spout-xlsx_sheet_with_dates_and_times.xlsx | ||||
| spout-xlsx_sheet_with_different_numeric_value_dates.xlsx | ||||
| spout-xlsx_sheet_with_different_numeric_value_times.xlsx | ||||
| spout-xlsx_sheet_with_dimensions_and_empty_cells.xlsx | ||||
| spout-xlsx_sheet_with_empty_cells.xlsx | ||||
| spout-xlsx_sheet_with_empty_rows_and_missing_row_index.xlsx | ||||
| spout-xlsx_sheet_with_empty_shared_string.xlsx | ||||
| spout-xlsx_sheet_with_formulas.xlsx | ||||
| spout-xlsx_sheet_with_lots_of_shared_strings.xlsx | ||||
| spout-xlsx_sheet_with_missing_cell_reference.xlsx | ||||
| spout-xlsx_sheet_with_no_cells.xlsx | ||||
| spout-xlsx_sheet_with_no_shared_strings_file.xlsx | ||||
| spout-xlsx_sheet_with_prefixed_xml_files.xlsx | ||||
| spout-xlsx_sheet_with_preserve_space_shared_strings.xlsx | ||||
| spout-xlsx_sheet_with_pronunciation.xlsx | ||||
| spout-xlsx_sheet_with_same_numeric_value_date_formatted_differently.xlsx | ||||
| spout-xlsx_sheet_with_untrimmed_inline_strings.xlsx | ||||
| spout-xlsx_sheet_with_zeros_in_row.xlsx | ||||
| spout-xlsx_sheet_without_dimensions_and_empty_cells.xlsx | ||||
| spout-xlsx_sheet_without_dimensions_but_spans_and_empty_cells.xlsx | ||||
| spout-xlsx_two_sheets_with_custom_names.xlsx | ||||
| spout-xlsx_two_sheets_with_inline_strings.xlsx | ||||
| spout-xlsx_two_sheets_with_shared_strings.xlsx | ||||
| spout-xlsx_two_sheets_with_sheets_definition_in_reverse_order.xlsx | ||||
| spreadsheet-parsexlsx_Test.xlsx | ||||
| spreadsheet-parsexlsx_bug-10.xlsx | ||||
| spreadsheet-parsexlsx_bug-11.xlsx | ||||
| @ -426,7 +457,7 @@ spreadsheet-parsexlsx_bug-5.xlsx | ||||
| spreadsheet-parsexlsx_bug-57.xlsx | ||||
| spreadsheet-parsexlsx_bug-6-2.xlsx | ||||
| spreadsheet-parsexlsx_bug-6.xlsx | ||||
| spreadsheet-parsexlsx_bug-61.xlsx | ||||
| # spreadsheet-parsexlsx_bug-61.xlsx | ||||
| spreadsheet-parsexlsx_bug-7.xlsx | ||||
| spreadsheet-parsexlsx_bug-8.xlsx | ||||
| spreadsheet-parsexlsx_bug-lock.xlsx | ||||
| @ -469,9 +500,9 @@ hyperlink_no_rels.xlsm | ||||
| number_format.xlsm | ||||
| number_format_russian.xlsm | ||||
| numfmt_1_russian.xlsm | ||||
| openpyxl_r_vba+comments.xlsm | ||||
| openpyxl_r_vba-comments-saved.xlsm | ||||
| openpyxl_r_vba-test.xlsm | ||||
| # openpyxl_r_vba+comments.xlsm | ||||
| # openpyxl_r_vba-comments-saved.xlsm | ||||
| # openpyxl_r_vba-test.xlsm | ||||
| # pivot_table_test.xlsm # xlml | ||||
| roo_1900_base.xlsm | ||||
| roo_1904_base.xlsm | ||||
| @ -507,6 +538,8 @@ formula_stress_test.ods | ||||
| merge_cells.ods | ||||
| number_format.ods | ||||
| rich_text_stress.ods | ||||
| roo-xls_numbers1.ods | ||||
| roo-xls_type_excel.ods | ||||
| roo_Bibelbund.ods | ||||
| roo_Bibelbund1.ods | ||||
| roo_advanced_header.ods | ||||
| @ -534,6 +567,32 @@ roo_time-test.ods | ||||
| roo_type_excel.ods | ||||
| roo_type_excelx.ods | ||||
| roo_whitespace.ods | ||||
| spout-ods_attack_billion_laughs.ods | ||||
| spout-ods_attack_quadratic_blowup.ods | ||||
| # spout-ods_file_corrupted.ods | ||||
| spout-ods_file_generated_by_excel_2010_windows.ods | ||||
| spout-ods_file_generated_by_excel_office_online.ods | ||||
| spout-ods_file_generated_by_libre_office.ods | ||||
| spout-ods_one_sheet_with_strings.ods | ||||
| spout-ods_sheet_with_all_cell_types.ods | ||||
| spout-ods_sheet_with_dates_and_times.ods | ||||
| spout-ods_sheet_with_empty_cells.ods | ||||
| spout-ods_sheet_with_empty_rows.ods | ||||
| spout-ods_sheet_with_formulas.ods | ||||
| spout-ods_sheet_with_hyperlinks.ods | ||||
| spout-ods_sheet_with_inline_font_formatting.ods | ||||
| spout-ods_sheet_with_invalid_date_time.ods.pending | ||||
| spout-ods_sheet_with_multiline_string.ods | ||||
| spout-ods_sheet_with_no_cells.ods | ||||
| spout-ods_sheet_with_number_columns_repeated.ods | ||||
| spout-ods_sheet_with_number_rows_repeated.ods | ||||
| spout-ods_sheet_with_only_one_cell.ods | ||||
| spout-ods_sheet_with_undefined_value_type.ods | ||||
| spout-ods_sheet_with_untrimmed_strings.ods | ||||
| spout-ods_sheet_with_various_spaces.ods | ||||
| spout-ods_sheet_with_zeros_in_row.ods | ||||
| spout-ods_two_sheets_with_custom_names.ods | ||||
| spout-ods_two_sheets_with_strings.ods | ||||
| sushi.ods | ||||
| biff5/NumberFormatCondition.xls | ||||
| biff5/RkNumber.xls | ||||
| @ -612,6 +671,7 @@ apachepoi_33082.xls | ||||
| apachepoi_34775.xls | ||||
| apachepoi_35564.xls | ||||
| apachepoi_35565.xls | ||||
| # apachepoi_35897-type4.xls ## password | ||||
| apachepoi_36947.xls | ||||
| apachepoi_37376.xls | ||||
| apachepoi_37630.xls | ||||
| @ -649,6 +709,7 @@ apachepoi_44840.xls | ||||
| apachepoi_44861.xls | ||||
| apachepoi_44891.xls | ||||
| apachepoi_44958.xls | ||||
| apachepoi_44958_1.xls | ||||
| apachepoi_45129.xls | ||||
| apachepoi_45290.xls | ||||
| apachepoi_45322.xls | ||||
| @ -659,6 +720,7 @@ apachepoi_45538_classic_Footer.xls | ||||
| apachepoi_45538_classic_Header.xls | ||||
| apachepoi_45538_form_Footer.xls | ||||
| apachepoi_45538_form_Header.xls | ||||
| apachepoi_45565.xls | ||||
| apachepoi_45672.xls | ||||
| apachepoi_45720.xls | ||||
| apachepoi_45761.xls | ||||
| @ -669,12 +731,14 @@ apachepoi_46137.xls | ||||
| apachepoi_46250.xls | ||||
| apachepoi_46368.xls | ||||
| apachepoi_46445.xls | ||||
| apachepoi_46515.xls | ||||
| apachepoi_46670_http.xls | ||||
| apachepoi_46670_local.xls | ||||
| apachepoi_46670_ref_airline.xls | ||||
| apachepoi_46904.xls | ||||
| apachepoi_47034.xls | ||||
| apachepoi_47154.xls | ||||
| apachepoi_47245_test.xls | ||||
| apachepoi_47251.xls | ||||
| apachepoi_47251_1.xls | ||||
| apachepoi_47701.xls | ||||
| @ -690,6 +754,7 @@ apachepoi_49096.xls | ||||
| apachepoi_49185.xls | ||||
| apachepoi_49219.xls | ||||
| apachepoi_49237.xls | ||||
| apachepoi_49423.xls | ||||
| apachepoi_49524.xls | ||||
| apachepoi_49529.xls | ||||
| apachepoi_49581.xls | ||||
| @ -717,6 +782,7 @@ apachepoi_51832.xls.pending | ||||
| apachepoi_52527.xls | ||||
| apachepoi_52575_main.xls | ||||
| apachepoi_52575_source.xls | ||||
| apachepoi_53109.xls | ||||
| apachepoi_53404.xls | ||||
| apachepoi_53433.xls | ||||
| apachepoi_53446.xls | ||||
| @ -730,24 +796,44 @@ apachepoi_54206.xls | ||||
| apachepoi_54500.xls | ||||
| apachepoi_54686_fraction_formats.xls | ||||
| apachepoi_55341_CellStyleBorder.xls | ||||
| apachepoi_55668.xls | ||||
| apachepoi_55906-MultiSheetRefs.xls | ||||
| apachepoi_55982.xls | ||||
| apachepoi_56325.xls | ||||
| apachepoi_56325a.xls | ||||
| apachepoi_56450.xls | ||||
| apachepoi_56482.xls | ||||
| apachepoi_56563a.xls | ||||
| apachepoi_56563b.xls | ||||
| apachepoi_56737.xls | ||||
| apachepoi_57003-FixedFunctionTestCaseData.xls | ||||
| apachepoi_57074.xls | ||||
| apachepoi_57163.xls | ||||
| apachepoi_57231_MixedGasReport.xls.pending | ||||
| apachepoi_57456.xls.pending | ||||
| apachepoi_57798.xls | ||||
| apachepoi_57925.xls | ||||
| apachepoi_59074.xls | ||||
| apachepoi_59264.xls | ||||
| apachepoi_59830.xls | ||||
| apachepoi_59858.xls | ||||
| apachepoi_60273.xls | ||||
| # apachepoi_60284.xls | ||||
| apachepoi_AbnormalSharedFormulaFlag.xls | ||||
| apachepoi_AreaErrPtg.xls | ||||
| apachepoi_BOOK_in_capitals.xls | ||||
| apachepoi_Basic_Expense_Template_2011.xls | ||||
| apachepoi_CodeFunctionTestCaseData.xls | ||||
| apachepoi_ColumnStyle1dp.xls | ||||
| apachepoi_ColumnStyle1dpColoured.xls | ||||
| apachepoi_ColumnStyleNone.xls | ||||
| apachepoi_ComplexFunctionTestCaseData.xls | ||||
| apachepoi_ConditionalFormattingSamples.xls | ||||
| apachepoi_ContinueRecordProblem.xls | ||||
| apachepoi_DBCSHeader.xls | ||||
| apachepoi_DBCSSheetName.xls | ||||
| apachepoi_DGet.xls | ||||
| apachepoi_DStar.xls | ||||
| apachepoi_DateFormats.xls | ||||
| apachepoi_DeltaFunctionTestCaseData.xls | ||||
| apachepoi_DrawingAndComments.xls | ||||
| @ -758,6 +844,7 @@ apachepoi_ErrPtg.xls | ||||
| apachepoi_FactDoubleFunctionTestCaseData.xls | ||||
| apachepoi_ForShifting.xls | ||||
| apachepoi_FormatChoiceTests.xls | ||||
| apachepoi_FormatKM.xls | ||||
| apachepoi_Formatting.xls | ||||
| apachepoi_FormulaEvalTestData.xls | ||||
| apachepoi_FormulaRefs.xls | ||||
| @ -775,6 +862,7 @@ apachepoi_IrrNpvTestCaseData.xls | ||||
| apachepoi_MRExtraLines.xls | ||||
| apachepoi_MatchFunctionTestCaseData.xls | ||||
| apachepoi_MissingBits.xls | ||||
| apachepoi_NewStyleConditionalFormattings.xls | ||||
| apachepoi_NoGutsRecords.xls | ||||
| apachepoi_OddStyleRecord.xls | ||||
| apachepoi_PercentPtg.xls | ||||
| @ -791,7 +879,9 @@ apachepoi_SheetWithDrawing.xls | ||||
| apachepoi_ShrinkToFit.xls | ||||
| apachepoi_Simple.xls | ||||
| apachepoi_SimpleChart.xls | ||||
| apachepoi_SimpleMacro.xls | ||||
| apachepoi_SimpleMultiCell.xls | ||||
| apachepoi_SimpleScatterChart.xls | ||||
| apachepoi_SimpleWithAutofilter.xls | ||||
| apachepoi_SimpleWithChoose.xls | ||||
| apachepoi_SimpleWithColours.xls | ||||
| @ -811,6 +901,7 @@ apachepoi_StringContinueRecords.xls | ||||
| apachepoi_StringFormulas.xls | ||||
| apachepoi_SubtotalsNested.xls | ||||
| apachepoi_TestRandBetween.xls | ||||
| apachepoi_Themes2.xls | ||||
| apachepoi_TwoSheetsNoneHidden.xls | ||||
| apachepoi_TwoSheetsOneHidden.xls | ||||
| # apachepoi_UncalcedRecord.xls # xlml | ||||
| @ -831,10 +922,13 @@ apachepoi_WithTwoHyperLinks.xls | ||||
| apachepoi_WrongFormulaRecordType.xls | ||||
| apachepoi_XRefCalc.xls | ||||
| apachepoi_XRefCalcData.xls | ||||
| apachepoi_ar.org.apsme.www_Form%20Inscripcion%20Curso%20NO%20Socios.xls | ||||
| apachepoi_at.gv.land-oberoesterreich.www_cps_rde_xbcr_SID-4A1B954F-5C07F98E_ooe_stat_download_bp10.xls | ||||
| apachepoi_atp.xls | ||||
| apachepoi_blankworkbook.xls | ||||
| apachepoi_bug_42794.xls | ||||
| apachepoi_colwidth.xls | ||||
| apachepoi_com.aida-tour.www_SPO_files_maldives%20august%20october.xls | ||||
| apachepoi_comments.xls | ||||
| apachepoi_countblankExamples.xls | ||||
| apachepoi_countifExamples.xls | ||||
| @ -861,24 +955,32 @@ apachepoi_excel_with_embeded.xls | ||||
| apachepoi_excelant.xls.pending | ||||
| apachepoi_externalFunctionExample.xls | ||||
| # apachepoi_finance.xls # xlml | ||||
| apachepoi_florida_data.ashx.xls | ||||
| apachepoi_intercept.xls | ||||
| apachepoi_mirrTest.xls | ||||
| apachepoi_missingFuncs44675.xls | ||||
| apachepoi_mortgage-calculation.xls | ||||
| apachepoi_multibookFormulaA.xls | ||||
| apachepoi_multibookFormulaB.xls | ||||
| apachepoi_named-cell-in-formula-test.xls | ||||
| apachepoi_named-cell-test.xls | ||||
| apachepoi_namedinput.xls | ||||
| apachepoi_noHeaderFooter47244.xls | ||||
| apachepoi_ole2-embedding.xls | ||||
| apachepoi_overlapSharedFormula.xls | ||||
| apachepoi_password.xls.pending | ||||
| apachepoi_rank.xls | ||||
| apachepoi_resize_compare.xls | ||||
| apachepoi_rk.xls | ||||
| apachepoi_shared_formulas.xls | ||||
| apachepoi_sumifformula.xls | ||||
| # apachepoi_sumifs.xls # xlml | ||||
| apachepoi_templateExcelWithAutofilter.xls | ||||
| apachepoi_testArraysAndTables.xls | ||||
| apachepoi_testEXCEL_3.xls | ||||
| apachepoi_testEXCEL_4.xls | ||||
| apachepoi_testEXCEL_5.xls | ||||
| apachepoi_testEXCEL_95.xls | ||||
| apachepoi_testNames.xls | ||||
| apachepoi_testRRaC.xls | ||||
| apachepoi_testRVA.xls | ||||
| @ -1091,40 +1193,41 @@ pyExcelerator_mini-mini.xls | ||||
| pyExcelerator_mini.xls | ||||
| pyExcelerator_oo14.xls | ||||
| rich_text_stress.xls | ||||
| roo_1900_base.xls | ||||
| roo_1904_base.xls | ||||
| roo_Bibelbund.xls | ||||
| roo_bad_excel_date.xls | ||||
| roo_bbu.xls | ||||
| roo_boolean.xls | ||||
| roo_borders.xls | ||||
| roo_bug-row-column-fixnum-float.xls | ||||
| roo_comments.xls | ||||
| roo_datetime.xls | ||||
| roo_datetime_floatconv.xls | ||||
| roo_emptysheets.xls | ||||
| roo_false_encoding.xls | ||||
| roo_formula.xls | ||||
| roo_formula_parse_error.xls | ||||
| roo_link.xls | ||||
| roo_matrix.xls | ||||
| roo_named_cells.xls | ||||
| roo_numbers1.xls | ||||
| roo_only_one_sheet.xls | ||||
| roo_paragraph.xls | ||||
| roo_prova.xls | ||||
| roo_simple_spreadsheet.xls | ||||
| roo_simple_spreadsheet_from_italo.xls | ||||
| roo_style.xls | ||||
| roo_time-test.xls | ||||
| roo_type_excelx.xls | ||||
| roo_type_openoffice.xls | ||||
| roo-xls_1900_base.xls | ||||
| roo-xls_1904_base.xls | ||||
| roo-xls_Bibelbund.xls | ||||
| roo-xls_bad_excel_date.xls | ||||
| roo-xls_bbu.xls | ||||
| roo-xls_boolean.xls | ||||
| roo-xls_borders.xls | ||||
| roo-xls_bug-row-column-fixnum-float.xls | ||||
| roo-xls_comments.xls | ||||
| roo-xls_datetime.xls | ||||
| roo-xls_datetime_floatconv.xls | ||||
| roo-xls_emptysheets.xls | ||||
| roo-xls_false_encoding.xls | ||||
| roo-xls_formula.xls | ||||
| roo-xls_formula_parse_error.xls | ||||
| roo-xls_link.xls | ||||
| roo-xls_matrix.xls | ||||
| roo-xls_named_cells.xls | ||||
| roo-xls_numbers1.xls | ||||
| roo-xls_only_one_sheet.xls | ||||
| roo-xls_paragraph.xls | ||||
| roo-xls_prova.xls | ||||
| roo-xls_simple_spreadsheet.xls | ||||
| roo-xls_simple_spreadsheet_from_italo.xls | ||||
| roo-xls_style.xls | ||||
| roo-xls_time-test.xls | ||||
| roo-xls_type_excelx.xls | ||||
| roo-xls_type_openoffice.xls | ||||
| roo_whitespace.xls | ||||
| smart_tags_2007.xls | ||||
| sushi.xls | ||||
| text_and_numbers.xls | ||||
| write.xls | ||||
| xlrd_Formate.xls | ||||
| # xlrd_biff4_no_format_no_window2.xls | ||||
| xlrd_formula_test_names.xls | ||||
| xlrd_formula_test_sjmachin.xls | ||||
| xlrd_issue20.xls | ||||
| @ -1135,7 +1238,6 @@ xlrd_xf_class.xls | ||||
| xlsx-stream-d-date-cell.xls | ||||
| AutoFilter.xml | ||||
| BlankSheetTypes.xml | ||||
| ErrorTypes.xml | ||||
| LONumbers-2010.xls.xml | ||||
| LONumbers-2010.xlsx.xml | ||||
| LONumbers-2011.xls.xml | ||||
| @ -1145,6 +1247,7 @@ NumberFormatCondition.xml | ||||
| RkNumber.xls.xml | ||||
| RkNumber.xlsb.xml | ||||
| RkNumber.xlsx.xml | ||||
| apachepoi_SampleSS.xml | ||||
| calendar_stress_test.xml.pending | ||||
| cell_style_simple.xml | ||||
| comments_stress_test.xls.xml | ||||
| @ -1197,26 +1300,28 @@ protect_stress_test_xml.xml | ||||
| rich_text_stress.xls.xml | ||||
| rich_text_stress.xlsb.xml | ||||
| rich_text_stress.xlsx.xml | ||||
| roo_Bibelbund.xml | ||||
| roo_bbu.xml | ||||
| roo_boolean.xml | ||||
| roo_borders.xml | ||||
| roo_bug-row-column-fixnum-float.xml | ||||
| roo_datetime.xml | ||||
| roo_datetime_floatconv.xml | ||||
| roo_emptysheets.xml | ||||
| roo_excel2003.xml | ||||
| roo_false_encoding.xml | ||||
| roo_formula.xml | ||||
| roo_formula_parse_error.xml | ||||
| roo_numbers1.xml | ||||
| roo_only_one_sheet.xml | ||||
| roo_paragraph.xml | ||||
| roo_simple_spreadsheet.xml | ||||
| roo_simple_spreadsheet_from_italo.xml | ||||
| roo_style.xml | ||||
| roo_time-test.xml | ||||
| roo_whitespace.xml | ||||
| roo-xls_Bibelbund.xml | ||||
| roo-xls_bbu.xml | ||||
| roo-xls_boolean.xml | ||||
| roo-xls_borders.xml | ||||
| roo-xls_bug-row-column-fixnum-float.xml | ||||
| roo-xls_datetime.xml | ||||
| roo-xls_datetime_floatconv.xml | ||||
| roo-xls_emptysheets.xml | ||||
| roo-xls_excel2003.xml | ||||
| roo-xls_excel2003_namespace.xml | ||||
| roo-xls_false_encoding.xml | ||||
| roo-xls_formula.xml | ||||
| roo-xls_formula_parse_error.xml | ||||
| roo-xls_numbers1.xml | ||||
| roo-xls_only_one_sheet.xml | ||||
| roo-xls_paragraph.xml | ||||
| roo-xls_simple_spreadsheet.xml | ||||
| roo-xls_simple_spreadsheet_from_italo.xml | ||||
| roo-xls_style.xml | ||||
| roo-xls_time-test.xml | ||||
| roo-xls_whitespace.xml | ||||
| # roo_sheet1.xml | ||||
| smart_tags_2007.xml | ||||
| sushi.xml | ||||
| text_and_numbers.xml | ||||
| @ -1229,3 +1334,15 @@ xlsx-stream-d-date-cell.xlsx.xml | ||||
| 2011/apachepoi_styles.xlsx.xml | ||||
| 2011/openpyxl_r_conditional-formatting.xlsx.xls | ||||
| 2011/roo_file_item_error.xlsx.xml | ||||
| 2013/apachepoi_29982.xls.xlsb | ||||
| 2013/apachepoi_43251.xls.xlsb | ||||
| 2013/apachepoi_44593.xls.xlsb ## xlsb loop timeout | ||||
| 2013/apachepoi_44643.xls.xlsb | ||||
| 2013/apachepoi_44958.xls.xlsb | ||||
| 2013/apachepoi_46136-NoWarnings.xls.xlsb | ||||
| 2013/apachepoi_48968.xls.xlsb | ||||
| 2013/apachepoi_50939.xls.xlsb | ||||
| 2013/apachepoi_54016.xls.xlsb | ||||
| 2013/apachepoi_ReadOnlyRecommended.xls.xlsb | ||||
| 2013/apachepoi_testArraysAndTables.xls.xlsb | ||||
| 
 | ||||
|  | ||||
| @ -79,14 +79,32 @@ var ws = sheet_from_array_of_arrays(data); | ||||
| wb.SheetNames.push(ws_name); | ||||
| wb.Sheets[ws_name] = ws; | ||||
| 
 | ||||
| /* TEST: simple formula */ | ||||
| ws['C1'].f = "A1+B1"; | ||||
| ws['C2'] = {t:'n', f:"A1+B1"}; | ||||
| 
 | ||||
| /* TEST: single-cell array formula */ | ||||
| ws['D1'] = {t:'n', f:"SUM(A1:C1*A1:C1)", F:"D1:D1"}; | ||||
| 
 | ||||
| /* TEST: multi-cell array formula */ | ||||
| ws['E1'] = {t:'n', f:"TRANSPOSE(A1:D1)", F:"E1:E4"}; | ||||
| ws['E2'] = {t:'n', F:"E1:E4"}; | ||||
| ws['E3'] = {t:'n', F:"E1:E4"}; | ||||
| ws['E4'] = {t:'n', F:"E1:E4"}; | ||||
| ws["!ref"] = "A1:E4"; | ||||
| 
 | ||||
| /* TEST: column widths */ | ||||
| ws['!cols'] = wscols; | ||||
| 
 | ||||
| console.log("JSON Data: "); console.log(XLSX.utils.sheet_to_json(ws, {header:1})); | ||||
| 
 | ||||
| 
 | ||||
| /* write file */ | ||||
| XLSX.writeFile(wb, 'sheetjs.xlsx'); | ||||
| XLSX.writeFile(wb, 'sheetjs.xlsx', {bookSST:true}); | ||||
| XLSX.writeFile(wb, 'sheetjs.xlsm'); | ||||
| XLSX.writeFile(wb, 'sheetjs.xlsb'); | ||||
| XLSX.writeFile(wb, 'sheetjs.xls', {bookType:'biff2'}); | ||||
| XLSX.writeFile(wb, 'sheetjs.xlsb'); // no formula
 | ||||
| XLSX.writeFile(wb, 'sheetjs.xls', {bookType:'biff2'}); // no formula
 | ||||
| XLSX.writeFile(wb, 'sheetjs.xml.xls', {bookType:'xlml'}); | ||||
| XLSX.writeFile(wb, 'sheetjs.ods'); | ||||
| XLSX.writeFile(wb, 'sheetjs.fods'); | ||||
| XLSX.writeFile(wb, 'sheetjs.csv'); | ||||
| @ -96,6 +114,7 @@ XLSX.readFile('sheetjs.xlsx'); | ||||
| XLSX.readFile('sheetjs.xlsm'); | ||||
| XLSX.readFile('sheetjs.xlsb'); | ||||
| XLSX.readFile('sheetjs.xls'); | ||||
| XLSX.readFile('sheetjs.xml.xls'); | ||||
| XLSX.readFile('sheetjs.ods'); | ||||
| XLSX.readFile('sheetjs.fods'); | ||||
| //XLSX.readFile('sheetjs.csv');
 | ||||
|  | ||||
							
								
								
									
										165
									
								
								xlsx.flow.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										165
									
								
								xlsx.flow.js
									
									
									
									
									
								
							| @ -422,7 +422,18 @@ function hashq(str/*:string*/)/*:string*/ { | ||||
| 	return o; | ||||
| } | ||||
| function rnd(val/*:number*/, d/*:number*/)/*:string*/ { var dd = Math.pow(10,d); return ""+(Math.round(val * dd)/dd); } | ||||
| function dec(val/*:number*/, d/*:number*/)/*:number*/ { return Math.round((val-Math.floor(val))*Math.pow(10,d)); } | ||||
| function dec(val/*:number*/, d/*:number*/)/*:number*/ { | ||||
| 	if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) { | ||||
| 		return 0; | ||||
| 	} | ||||
| 	return Math.round((val-Math.floor(val))*Math.pow(10,d)); | ||||
| } | ||||
| function carry(val/*:number*/, d/*:number*/)/*:number*/ { | ||||
| 	if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) { | ||||
| 		return 1; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| function flr(val/*:number*/)/*:string*/ { if(val < 2147483647 && val > -2147483648) return ""+(val >= 0 ? (val|0) : (val-1|0)); return ""+Math.floor(val); } | ||||
| function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/ { | ||||
| 	if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) { | ||||
| @ -444,8 +455,7 @@ function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string | ||||
| 	if((r = fmt.match(frac1))) return write_num_f1(r, aval, sign); | ||||
| 	if(fmt.match(/^#+0+$/)) return sign + pad0r(aval,fmt.length - fmt.indexOf("0")); | ||||
| 	if((r = fmt.match(dec1))) { | ||||
| 		// $FlowIgnore
 | ||||
| 		o = rnd(val, r[1].length).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.(\d*)$/,function($$, $1) { return "." + $1 + fill("0", r[1].length-$1.length); }); | ||||
| 		o = rnd(val, r[1].length).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.(\d*)$/,function($$, $1) { return "." + $1 + fill("0", /*::(*/r/*::||[""])*/[1].length-$1.length); }); | ||||
| 		return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,"."); | ||||
| 	} | ||||
| 	fmt = fmt.replace(/^#+([0.])/, "$1"); | ||||
| @ -454,7 +464,7 @@ function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string | ||||
| 	} | ||||
| 	if((r = fmt.match(/^#,##0(\.?)$/))) return sign + commaify(pad0r(aval,0)); | ||||
| 	if((r = fmt.match(/^#,##0\.([#0]*0)$/))) { | ||||
| 		return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(""+(Math.floor(val))) + "." + pad0(dec(val, r[1].length),r[1].length); | ||||
| 		return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(""+(Math.floor(val) + carry(val, r[1].length))) + "." + pad0(dec(val, r[1].length),r[1].length); | ||||
| 	} | ||||
| 	if((r = fmt.match(/^#,#*,#0/))) return write_num_flt(type,fmt.replace(/^#,#*,/,""),val); | ||||
| 	if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) { | ||||
| @ -8201,8 +8211,18 @@ function ods_to_csf_formula(f/*:string*/)/*:string*/ { | ||||
| 		f = f.substr(1); | ||||
| 		if(f.charCodeAt(0) == 61) f = f.substr(1); | ||||
| 	} | ||||
| 	f = f.replace(/COM\.MICROSOFT\./g, ""); | ||||
| 	/* Part 3 Section 5.8 References */ | ||||
| 	return f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, "$1").replace(/\./g, ""); | ||||
| 	f = f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, function($$, $1) { return $1.replace(/\./g,""); }); | ||||
| 	/* TODO: something other than this */ | ||||
| 	f = f.replace(/\[.(#[A-Z]*[?!])\]/g, "$1"); | ||||
| 	return f.replace(/[;~]/g,",").replace(/\|/g,";"); | ||||
| } | ||||
| 
 | ||||
| function csf_to_ods_formula(f/*:string*/)/*:string*/ { | ||||
| 	var o = "of:=" + f.replace(crefregex, "$1[.$2$3$4$5]").replace(/\]:\[/g,":"); | ||||
| 	/* TODO: something other than this */ | ||||
| 	return o.replace(/;/g, "|").replace(/,/g,";"); | ||||
| } | ||||
| var strs = {}; // shared strings
 | ||||
| var _ssfopts = {}; // spreadsheet formatting options
 | ||||
| @ -8390,7 +8410,7 @@ function write_ws_xml_cols(ws, cols)/*:string*/ { | ||||
| } | ||||
| 
 | ||||
| function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) { | ||||
| 	if(cell.v === undefined || cell.t === 'z') return ""; | ||||
| 	if(cell.v === undefined && cell.f === undefined || cell.t === 'z') return ""; | ||||
| 	var vv = ""; | ||||
| 	var oldt = cell.t, oldv = cell.v; | ||||
| 	switch(cell.t) { | ||||
| @ -8416,7 +8436,7 @@ function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) { | ||||
| 		case 'd': o.t = "d"; break; | ||||
| 		case 'b': o.t = "b"; break; | ||||
| 		case 'e': o.t = "e"; break; | ||||
| 		default: | ||||
| 		default: if(cell.v == null) { delete cell.t; break; } | ||||
| 			if(opts.bookSST) { | ||||
| 				v = writetag('v', ''+get_sst_id(opts.Strings, cell.v)); | ||||
| 				o.t = "s"; break; | ||||
| @ -8424,6 +8444,10 @@ function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) { | ||||
| 			o.t = "str"; break; | ||||
| 	} | ||||
| 	if(cell.t != oldt) { cell.t = oldt; cell.v = oldv; } | ||||
| 	if(cell.f) { | ||||
| 		var ff = cell.F && cell.F.substr(0, ref.length) == ref ? {t:"array", ref:cell.F} : null; | ||||
| 		v = writextag('f', escapexml(cell.f), ff) + (cell.v != null ? v : ""); | ||||
| 	} | ||||
| 	return writextag('c', v, o); | ||||
| } | ||||
| 
 | ||||
| @ -8479,7 +8503,8 @@ return function parse_ws_xml_data(sdata, s, opts, guess) { | ||||
| 			if((cref=d.match(match_v))!= null && /*::cref != null && */cref[1] !== '') p.v=unescapexml(cref[1]); | ||||
| 			if(opts.cellFormula) { | ||||
| 				if((cref=d.match(match_f))!= null && /*::cref != null && */cref[1] !== '') { | ||||
| 					p.f=unescapexml(utf8read(cref[1])); | ||||
| 					/* TODO: match against XLSXFutureFunctions */ | ||||
| 					p.f=unescapexml(utf8read(cref[1])).replace(/_xlfn\./,""); | ||||
| 					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]); | ||||
| @ -9842,7 +9867,7 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, a | ||||
| 		case 'DateTime': | ||||
| 			cell.v = (Date.parse(xml) - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000); | ||||
| 			if(cell.v !== cell.v) cell.v = unescapexml(xml); | ||||
| 			else if(cell.v >= 1 && cell.v<60) cell.v = cell.v -1; | ||||
| 			else if(cell.v<60) cell.v = cell.v -1; | ||||
| 			if(!nf || nf == "General") nf = "yyyy-mm-dd"; | ||||
| 			/* falls through */ | ||||
| 		case 'Number': | ||||
| @ -9984,6 +10009,7 @@ function parse_xlml_xml(d, opts)/*:Workbook*/ { | ||||
| 				sheetname = unescapexml(tmp.Name); | ||||
| 				cursheet = {}; | ||||
| 				mergecells = []; | ||||
| 				arrayf = []; | ||||
| 			} | ||||
| 			break; | ||||
| 		case 'Table': | ||||
| @ -10493,10 +10519,14 @@ function write_sty_xlml(wb, opts)/*:string*/ { | ||||
| } | ||||
| /* TODO */ | ||||
| function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr)/*:string*/{ | ||||
| 	if(!cell || cell.v === undefined) return "<Cell></Cell>"; | ||||
| 	if(!cell || cell.v == undefined && cell.f == undefined) return "<Cell></Cell>"; | ||||
| 
 | ||||
| 	var attr = {}; | ||||
| 	if(cell.f) attr["ss:Formula"] = "=" + escapexml(a1_to_rc(cell.f, addr)); | ||||
| 	if(cell.F && cell.F.substr(0, ref.length) == ref) { | ||||
| 		var end = decode_cell(cell.F.substr(ref.length + 1)); | ||||
| 		attr["ss:ArrayRange"] = "RC:R" + (end.r == addr.r ? "" : "[" + (end.r - addr.r) + "]") + "C" + (end.c == addr.c ? "" : "[" + (end.c - addr.c) + "]"); | ||||
| 	} | ||||
| 
 | ||||
| 	if(ws['!merges']) { | ||||
| 		var marr = ws['!merges']; | ||||
| @ -10514,9 +10544,9 @@ function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr)/*:string*/{ | ||||
| 		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 's':  t = 'String'; p = escapexml(cell.v||""); break; | ||||
| 		case 's': t = 'String'; p = escapexml(cell.v||""); break; | ||||
| 	} | ||||
| 	var m = '<Data ss:Type="' + t + '">' + p + '</Data>'; | ||||
| 	var m = '<Data ss:Type="' + t + '">' + (cell.v != null ? p : "") + '</Data>'; | ||||
| 
 | ||||
| 	return writextag("Cell", m, attr); | ||||
| } | ||||
| @ -10699,6 +10729,19 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 			if(cell.r + 1 > range.e.r) range.e.r = cell.r + 1; | ||||
| 			if(cell.c + 1 > range.e.c) range.e.c = cell.c + 1; | ||||
| 		} | ||||
| 		if(options.cellFormula && line.f) { | ||||
| 			for(var afi = 0; afi < 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); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		if(options.sheetRows && lastcell.r >= options.sheetRows) cell_valid = false; | ||||
| 		else out[last_cell] = line; | ||||
| 	}; | ||||
| @ -10851,7 +10894,9 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 					else cur_sheet = (Directory[s] || {name:""}).name; | ||||
| 					mergecells = []; | ||||
| 					objects = []; | ||||
| 					array_formulae = []; opts.arrayf = array_formulae; | ||||
| 				} break; | ||||
| 
 | ||||
| 				case 'Number': case 'BIFF2NUM': case 'BIFF2INT': { | ||||
| 					temp_val = {ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:'n'}; | ||||
| 					safe_format_xf(temp_val, options, wb.opts.Date1904); | ||||
| @ -10876,44 +10921,43 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 					} | ||||
| 				} break; | ||||
| 				case 'Formula': { | ||||
| 					switch(val.val) { | ||||
| 						case 'String': last_formula = val; break; | ||||
| 						case 'Array Formula': throw "Array Formula unsupported"; | ||||
| 						default: | ||||
| 							temp_val = ({v:val.val, ixfe:val.cell.ixfe, t:val.tt}/*:any*/); | ||||
| 							temp_val.XF = XFs[temp_val.ixfe]; | ||||
| 							if(options.cellFormula) { | ||||
| 								var _f = val.formula; | ||||
| 								if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') { | ||||
| 									var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1]; | ||||
| 									var _fe = encode_cell({r:_fr, c:_fc}); | ||||
| 									if(shared_formulae[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); | ||||
| 									else temp_val.F = (out[_fe] || {}).F; | ||||
| 								} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); | ||||
| 							} | ||||
| 							safe_format_xf(temp_val, options, wb.opts.Date1904); | ||||
| 							addcell(val.cell, temp_val, options); | ||||
| 							last_formula = val; | ||||
| 					if(val.val == 'String') { last_formula = val; break; } | ||||
| 					temp_val = ({v:val.val, ixfe:val.cell.ixfe, t:val.tt}/*:any*/); | ||||
| 					temp_val.XF = XFs[temp_val.ixfe]; | ||||
| 					if(options.cellFormula) { | ||||
| 						var _f = val.formula; | ||||
| 						if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') { | ||||
| 							var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1]; | ||||
| 							var _fe = encode_cell({r:_fr, c:_fc}); | ||||
| 							if(shared_formulae[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); | ||||
| 							else temp_val.F = (out[_fe] || {}).F; | ||||
| 						} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); | ||||
| 					} | ||||
| 					safe_format_xf(temp_val, options, wb.opts.Date1904); | ||||
| 					addcell(val.cell, temp_val, options); | ||||
| 					last_formula = val; | ||||
| 				} break; | ||||
| 				case 'String': { | ||||
| 					if(last_formula) { | ||||
| 					if(last_formula) { /* technically always true */ | ||||
| 						last_formula.val = val; | ||||
| 						temp_val = ({v:last_formula.val, ixfe:last_formula.cell.ixfe, t:'s'}/*:any*/); | ||||
| 						temp_val = ({v:val, ixfe:last_formula.cell.ixfe, t:'s'}/*:any*/); | ||||
| 						temp_val.XF = XFs[temp_val.ixfe]; | ||||
| 						if(options.cellFormula) temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts); | ||||
| 						if(options.cellFormula) { | ||||
| 							temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts); | ||||
| 						} | ||||
| 						safe_format_xf(temp_val, options, wb.opts.Date1904); | ||||
| 						addcell(last_formula.cell, temp_val, options); | ||||
| 						last_formula = null; | ||||
| 					} | ||||
| 					} else throw new Error("String record expects Formula"); | ||||
| 				} break; | ||||
| 				case 'Array': { | ||||
| 					array_formulae.push(val); | ||||
| 					if(options.cellFormula && out[last_cell]) { | ||||
| 					var _arraystart = encode_cell(val[0].s); | ||||
| 					if(options.cellFormula && out[_arraystart]) { | ||||
| 						if(!last_formula) break; /* technically unreachable */ | ||||
| 						if(!last_cell || !out[last_cell]) break; /* technically unreachable */ | ||||
| 						out[last_cell].f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts); | ||||
| 						out[last_cell].F = encode_range(val[0]); | ||||
| 						if(!_arraystart || !out[_arraystart]) break; | ||||
| 						out[_arraystart].f = ""+stringify_formula(val[1], range, val[0], supbooks, opts); | ||||
| 						out[_arraystart].F = encode_range(val[0]); | ||||
| 					} | ||||
| 				} break; | ||||
| 				case 'ShrFmla': { | ||||
| @ -10952,6 +10996,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 					safe_format_xf(temp_val, options, wb.opts.Date1904); | ||||
| 					addcell({c:val.c, r:val.r}, temp_val, options); | ||||
| 					break; | ||||
| 
 | ||||
| 				case 'Dimensions': { | ||||
| 					if(file_depth === 1) range = val; /* TODO: stack */ | ||||
| 				} break; | ||||
| @ -12602,20 +12647,20 @@ function write_BIFF2LABEL(r, c, val) { | ||||
| } | ||||
| 
 | ||||
| function write_ws_biff_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts) { | ||||
| 	switch(cell.t) { | ||||
| 	if(cell.v != null) switch(cell.t) { | ||||
| 		case 'n': | ||||
| 			if((cell.v == (cell.v|0)) && (cell.v >= 0) && (cell.v < 65536)) | ||||
| 				write_biff_rec(ba, 0x0002, write_BIFF2INT(R, C, cell.v)); | ||||
| 			else | ||||
| 				write_biff_rec(ba, 0x0003, write_BIFF2NUMBER(R,C, cell.v)); | ||||
| 			break; | ||||
| 		case 'b': case 'e': write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); break; | ||||
| 			return; | ||||
| 		case 'b': case 'e': write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); return; | ||||
| 		/* TODO: codepage, sst */ | ||||
| 		case 's': case 'str': | ||||
| 			write_biff_rec(ba, 0x0004, write_BIFF2LABEL(R, C, cell.v)); | ||||
| 			break; | ||||
| 		default: write_biff_rec(ba, 0x0001, write_BIFF2Cell(null, R, C)); | ||||
| 			return; | ||||
| 	} | ||||
| 	write_biff_rec(ba, 0x0001, write_BIFF2Cell(null, R, C)); | ||||
| } | ||||
| 
 | ||||
| function write_biff_ws(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbook*/) { | ||||
| @ -12761,6 +12806,7 @@ var parse_content_xml = (function() { | ||||
| 					ctag = parsexmltag(Rn[0], false); | ||||
| 					q = ({t:ctag['数据类型'] || ctag['value-type'], v:null/*:: , z:null, w:""*/}/*:any*/); | ||||
| 					if(opts.cellFormula) { | ||||
| 						if(ctag.formula) ctag.formula = unescapexml(ctag.formula); | ||||
| 						if(ctag['number-matrix-columns-spanned'] && ctag['number-matrix-rows-spanned']) { | ||||
| 							mR = parseInt(ctag['number-matrix-rows-spanned'],10) || 0; | ||||
| 							mC = parseInt(ctag['number-matrix-columns-spanned'],10) || 0; | ||||
| @ -13108,11 +13154,22 @@ var write_content_xml/*:{(wb:any, opts:any):string}*/ = (function() { | ||||
| 				} | ||||
| 				if(skip) { o.push(covered_cell_xml); continue; } | ||||
| 				var ref = encode_cell({r:R, c:C}), cell = ws[ref]; | ||||
| 				var fmla = ""; | ||||
| 				if(cell && cell.f) { | ||||
| 					fmla = ' table:formula="' + escapexml(csf_to_ods_formula(cell.f)) + '"'; | ||||
| 					if(cell.F) { | ||||
| 						if(cell.F.substr(0, ref.length) == ref) { | ||||
| 							var _Fref = decode_range(cell.F); | ||||
| 							fmla += ' table:number-matrix-columns-spanned="' + (_Fref.e.c - _Fref.s.c + 1)+ '"'; | ||||
| 							fmla += ' table:number-matrix-rows-spanned="' + (_Fref.e.r - _Fref.s.r + 1) + '"'; | ||||
| 						} else fmla = ""; | ||||
| 					} | ||||
| 				} | ||||
| 				if(cell) switch(cell.t) { | ||||
| 					case 'b': o.push(cell_begin + mxml + vt + '"boolean" office:boolean-value="' + (cell.v ? 'true' : 'false') + '">' + p_begin + (cell.v ? 'TRUE' : 'FALSE') + p_end + cell_end); break; | ||||
| 					case 'n': o.push(cell_begin + mxml + vt + '"float" office:value="' + cell.v + '">' + p_begin + (cell.w||cell.v) + p_end + cell_end); break; | ||||
| 					case 's': case 'str': o.push(cell_begin + mxml + vt + '"string">' + p_begin + escapexml(cell.v) + p_end + cell_end); break; | ||||
| 					case 'd': o.push(cell_begin + mxml + vt + '"date" office:date-value="' + (new Date(cell.v).toISOString()) + '">' + p_begin + (cell.w||(new Date(cell.v).toISOString())) + p_end + cell_end); break; | ||||
| 					case 'b': o.push(cell_begin + mxml + vt + '"boolean" office:boolean-value="' + (cell.v ? 'true' : 'false') + '"' + fmla + '>' + p_begin + (cell.v ? 'TRUE' : 'FALSE') + p_end + cell_end); break; | ||||
| 					case 'n': o.push(cell_begin + mxml + vt + '"float" office:value="' + cell.v + '"' + fmla + '>' + p_begin + (cell.w||cell.v) + p_end + cell_end); break; | ||||
| 					case 's': case 'str': o.push(cell_begin + mxml + vt + '"string"' + fmla + '>' + p_begin + escapexml(cell.v) + p_end + cell_end); break; | ||||
| 					case 'd': o.push(cell_begin + mxml + vt + '"date" office:date-value="' + (new Date(cell.v).toISOString()) + '"' + fmla + '>' + p_begin + (cell.w||(new Date(cell.v).toISOString())) + p_end + cell_end); break; | ||||
| 					//case 'e':
 | ||||
| 					default: o.push(null_cell_xml); | ||||
| 				} else o.push(null_cell_xml); | ||||
| @ -13127,7 +13184,7 @@ var write_content_xml/*:{(wb:any, opts:any):string}*/ = (function() { | ||||
| 		var o = [XML_HEADER]; | ||||
| 		/* 3.1.3.2 */ | ||||
| 		if(opts.bookType == "fods") o.push('<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.spreadsheet">'); | ||||
| 		else o.push('<office:document-content office:version="1.2" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0">\n'); // TODO
 | ||||
| 		else o.push('<office:document-content office:version="1.2" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2">\n'); // TODO
 | ||||
| 		o.push('  <office:body>\n'); | ||||
| 		o.push('    <office:spreadsheet>\n'); | ||||
| 		for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts)); | ||||
| @ -13749,9 +13806,15 @@ function sheet_to_csv(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) { | ||||
| 		rr = encode_row(R); | ||||
| 		for(C = r.s.c; C <= r.e.c; ++C) { | ||||
| 			val = sheet[cols[C] + rr]; | ||||
| 			txt = val !== undefined ? ''+format_cell(val) : ""; | ||||
| 			for(i = 0, cc = 0; i !== txt.length; ++i) if((cc = txt.charCodeAt(i)) === fs || cc === rs || cc === 34) { | ||||
| 				txt = "\"" + txt.replace(qreg, '""') + "\""; break; } | ||||
| 			if(val == null) txt = ""; | ||||
| 			else if(val.v != null) { | ||||
| 				txt = ''+format_cell(val); | ||||
| 				for(i = 0, cc = 0; i !== txt.length; ++i) if((cc = txt.charCodeAt(i)) === fs || cc === rs || cc === 34) { | ||||
| 					txt = "\"" + txt.replace(qreg, '""') + "\""; break; } | ||||
| 			} else if(val.f != null && !val.F) { | ||||
| 				txt = '=' + val.f; if(txt.indexOf(",") >= 0) txt = '"' + txt.replace(qreg, '""') + '"'; | ||||
| 			} else txt = ""; | ||||
| 			/* NOTE: Excel CSV does not support array formulae */ | ||||
| 			row += (C === r.s.c ? "" : FS) + txt; | ||||
| 		} | ||||
| 		out += row + RS; | ||||
|  | ||||
							
								
								
									
										163
									
								
								xlsx.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										163
									
								
								xlsx.js
									
									
									
									
									
								
							| @ -403,7 +403,18 @@ function hashq(str) { | ||||
| 	return o; | ||||
| } | ||||
| function rnd(val, d) { var dd = Math.pow(10,d); return ""+(Math.round(val * dd)/dd); } | ||||
| function dec(val, d) { return Math.round((val-Math.floor(val))*Math.pow(10,d)); } | ||||
| function dec(val, d) { | ||||
| 	if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) { | ||||
| 		return 0; | ||||
| 	} | ||||
| 	return Math.round((val-Math.floor(val))*Math.pow(10,d)); | ||||
| } | ||||
| function carry(val, d) { | ||||
| 	if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) { | ||||
| 		return 1; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| function flr(val) { if(val < 2147483647 && val > -2147483648) return ""+(val >= 0 ? (val|0) : (val-1|0)); return ""+Math.floor(val); } | ||||
| function write_num_flt(type, fmt, val) { | ||||
| 	if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) { | ||||
| @ -425,7 +436,6 @@ function write_num_flt(type, fmt, val) { | ||||
| 	if((r = fmt.match(frac1))) return write_num_f1(r, aval, sign); | ||||
| 	if(fmt.match(/^#+0+$/)) return sign + pad0r(aval,fmt.length - fmt.indexOf("0")); | ||||
| 	if((r = fmt.match(dec1))) { | ||||
| 		// $FlowIgnore
 | ||||
| 		o = rnd(val, r[1].length).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.(\d*)$/,function($$, $1) { return "." + $1 + fill("0", r[1].length-$1.length); }); | ||||
| 		return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,"."); | ||||
| 	} | ||||
| @ -435,7 +445,7 @@ function write_num_flt(type, fmt, val) { | ||||
| 	} | ||||
| 	if((r = fmt.match(/^#,##0(\.?)$/))) return sign + commaify(pad0r(aval,0)); | ||||
| 	if((r = fmt.match(/^#,##0\.([#0]*0)$/))) { | ||||
| 		return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(""+(Math.floor(val))) + "." + pad0(dec(val, r[1].length),r[1].length); | ||||
| 		return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(""+(Math.floor(val) + carry(val, r[1].length))) + "." + pad0(dec(val, r[1].length),r[1].length); | ||||
| 	} | ||||
| 	if((r = fmt.match(/^#,#*,#0/))) return write_num_flt(type,fmt.replace(/^#,#*,/,""),val); | ||||
| 	if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) { | ||||
| @ -8148,8 +8158,18 @@ function ods_to_csf_formula(f) { | ||||
| 		f = f.substr(1); | ||||
| 		if(f.charCodeAt(0) == 61) f = f.substr(1); | ||||
| 	} | ||||
| 	f = f.replace(/COM\.MICROSOFT\./g, ""); | ||||
| 	/* Part 3 Section 5.8 References */ | ||||
| 	return f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, "$1").replace(/\./g, ""); | ||||
| 	f = f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, function($$, $1) { return $1.replace(/\./g,""); }); | ||||
| 	/* TODO: something other than this */ | ||||
| 	f = f.replace(/\[.(#[A-Z]*[?!])\]/g, "$1"); | ||||
| 	return f.replace(/[;~]/g,",").replace(/\|/g,";"); | ||||
| } | ||||
| 
 | ||||
| function csf_to_ods_formula(f) { | ||||
| 	var o = "of:=" + f.replace(crefregex, "$1[.$2$3$4$5]").replace(/\]:\[/g,":"); | ||||
| 	/* TODO: something other than this */ | ||||
| 	return o.replace(/;/g, "|").replace(/,/g,";"); | ||||
| } | ||||
| var strs = {}; // shared strings
 | ||||
| var _ssfopts = {}; // spreadsheet formatting options
 | ||||
| @ -8337,7 +8357,7 @@ function write_ws_xml_cols(ws, cols) { | ||||
| } | ||||
| 
 | ||||
| function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) { | ||||
| 	if(cell.v === undefined || cell.t === 'z') return ""; | ||||
| 	if(cell.v === undefined && cell.f === undefined || cell.t === 'z') return ""; | ||||
| 	var vv = ""; | ||||
| 	var oldt = cell.t, oldv = cell.v; | ||||
| 	switch(cell.t) { | ||||
| @ -8363,7 +8383,7 @@ function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) { | ||||
| 		case 'd': o.t = "d"; break; | ||||
| 		case 'b': o.t = "b"; break; | ||||
| 		case 'e': o.t = "e"; break; | ||||
| 		default: | ||||
| 		default: if(cell.v == null) { delete cell.t; break; } | ||||
| 			if(opts.bookSST) { | ||||
| 				v = writetag('v', ''+get_sst_id(opts.Strings, cell.v)); | ||||
| 				o.t = "s"; break; | ||||
| @ -8371,6 +8391,10 @@ function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) { | ||||
| 			o.t = "str"; break; | ||||
| 	} | ||||
| 	if(cell.t != oldt) { cell.t = oldt; cell.v = oldv; } | ||||
| 	if(cell.f) { | ||||
| 		var ff = cell.F && cell.F.substr(0, ref.length) == ref ? {t:"array", ref:cell.F} : null; | ||||
| 		v = writextag('f', escapexml(cell.f), ff) + (cell.v != null ? v : ""); | ||||
| 	} | ||||
| 	return writextag('c', v, o); | ||||
| } | ||||
| 
 | ||||
| @ -8426,7 +8450,8 @@ return function parse_ws_xml_data(sdata, s, opts, guess) { | ||||
| 			if((cref=d.match(match_v))!= null && cref[1] !== '') p.v=unescapexml(cref[1]); | ||||
| 			if(opts.cellFormula) { | ||||
| 				if((cref=d.match(match_f))!= null && cref[1] !== '') { | ||||
| 					p.f=unescapexml(utf8read(cref[1])); | ||||
| 					/* TODO: match against XLSXFutureFunctions */ | ||||
| 					p.f=unescapexml(utf8read(cref[1])).replace(/_xlfn\./,""); | ||||
| 					if(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]); | ||||
| @ -9787,7 +9812,7 @@ function parse_xlml_data(xml, ss, data, cell, base, styles, csty, row, arrayf, o | ||||
| 		case 'DateTime': | ||||
| 			cell.v = (Date.parse(xml) - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000); | ||||
| 			if(cell.v !== cell.v) cell.v = unescapexml(xml); | ||||
| 			else if(cell.v >= 1 && cell.v<60) cell.v = cell.v -1; | ||||
| 			else if(cell.v<60) cell.v = cell.v -1; | ||||
| 			if(!nf || nf == "General") nf = "yyyy-mm-dd"; | ||||
| 			/* falls through */ | ||||
| 		case 'Number': | ||||
| @ -9928,6 +9953,7 @@ for(var cma = c; cma <= cc; ++cma) { | ||||
| 				sheetname = unescapexml(tmp.Name); | ||||
| 				cursheet = {}; | ||||
| 				mergecells = []; | ||||
| 				arrayf = []; | ||||
| 			} | ||||
| 			break; | ||||
| 		case 'Table': | ||||
| @ -10436,10 +10462,14 @@ function write_sty_xlml(wb, opts) { | ||||
| } | ||||
| /* TODO */ | ||||
| function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr){ | ||||
| 	if(!cell || cell.v === undefined) return "<Cell></Cell>"; | ||||
| 	if(!cell || cell.v == undefined && cell.f == undefined) return "<Cell></Cell>"; | ||||
| 
 | ||||
| 	var attr = {}; | ||||
| 	if(cell.f) attr["ss:Formula"] = "=" + escapexml(a1_to_rc(cell.f, addr)); | ||||
| 	if(cell.F && cell.F.substr(0, ref.length) == ref) { | ||||
| 		var end = decode_cell(cell.F.substr(ref.length + 1)); | ||||
| 		attr["ss:ArrayRange"] = "RC:R" + (end.r == addr.r ? "" : "[" + (end.r - addr.r) + "]") + "C" + (end.c == addr.c ? "" : "[" + (end.c - addr.c) + "]"); | ||||
| 	} | ||||
| 
 | ||||
| 	if(ws['!merges']) { | ||||
| 		var marr = ws['!merges']; | ||||
| @ -10457,9 +10487,9 @@ function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr){ | ||||
| 		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 's':  t = 'String'; p = escapexml(cell.v||""); break; | ||||
| 		case 's': t = 'String'; p = escapexml(cell.v||""); break; | ||||
| 	} | ||||
| 	var m = '<Data ss:Type="' + t + '">' + p + '</Data>'; | ||||
| 	var m = '<Data ss:Type="' + t + '">' + (cell.v != null ? p : "") + '</Data>'; | ||||
| 
 | ||||
| 	return writextag("Cell", m, attr); | ||||
| } | ||||
| @ -10642,6 +10672,19 @@ function parse_workbook(blob, options) { | ||||
| 			if(cell.r + 1 > range.e.r) range.e.r = cell.r + 1; | ||||
| 			if(cell.c + 1 > range.e.c) range.e.c = cell.c + 1; | ||||
| 		} | ||||
| 		if(options.cellFormula && line.f) { | ||||
| 			for(var afi = 0; afi < 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); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		if(options.sheetRows && lastcell.r >= options.sheetRows) cell_valid = false; | ||||
| 		else out[last_cell] = line; | ||||
| 	}; | ||||
| @ -10794,7 +10837,9 @@ function parse_workbook(blob, options) { | ||||
| 					else cur_sheet = (Directory[s] || {name:""}).name; | ||||
| 					mergecells = []; | ||||
| 					objects = []; | ||||
| 					array_formulae = []; opts.arrayf = array_formulae; | ||||
| 				} break; | ||||
| 
 | ||||
| 				case 'Number': case 'BIFF2NUM': case 'BIFF2INT': { | ||||
| 					temp_val = {ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:'n'}; | ||||
| 					safe_format_xf(temp_val, options, wb.opts.Date1904); | ||||
| @ -10819,44 +10864,43 @@ function parse_workbook(blob, options) { | ||||
| 					} | ||||
| 				} break; | ||||
| 				case 'Formula': { | ||||
| 					switch(val.val) { | ||||
| 						case 'String': last_formula = val; break; | ||||
| 						case 'Array Formula': throw "Array Formula unsupported"; | ||||
| 						default: | ||||
| 							temp_val = ({v:val.val, ixfe:val.cell.ixfe, t:val.tt}); | ||||
| 							temp_val.XF = XFs[temp_val.ixfe]; | ||||
| 							if(options.cellFormula) { | ||||
| 								var _f = val.formula; | ||||
| 								if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') { | ||||
| 									var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1]; | ||||
| 									var _fe = encode_cell({r:_fr, c:_fc}); | ||||
| 									if(shared_formulae[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); | ||||
| 									else temp_val.F = (out[_fe] || {}).F; | ||||
| 								} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); | ||||
| 							} | ||||
| 							safe_format_xf(temp_val, options, wb.opts.Date1904); | ||||
| 							addcell(val.cell, temp_val, options); | ||||
| 							last_formula = val; | ||||
| 					if(val.val == 'String') { last_formula = val; break; } | ||||
| 					temp_val = ({v:val.val, ixfe:val.cell.ixfe, t:val.tt}); | ||||
| 					temp_val.XF = XFs[temp_val.ixfe]; | ||||
| 					if(options.cellFormula) { | ||||
| 						var _f = val.formula; | ||||
| 						if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') { | ||||
| 							var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1]; | ||||
| 							var _fe = encode_cell({r:_fr, c:_fc}); | ||||
| 							if(shared_formulae[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); | ||||
| 							else temp_val.F = (out[_fe] || {}).F; | ||||
| 						} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); | ||||
| 					} | ||||
| 					safe_format_xf(temp_val, options, wb.opts.Date1904); | ||||
| 					addcell(val.cell, temp_val, options); | ||||
| 					last_formula = val; | ||||
| 				} break; | ||||
| 				case 'String': { | ||||
| 					if(last_formula) { | ||||
| 					if(last_formula) { /* technically always true */ | ||||
| 						last_formula.val = val; | ||||
| 						temp_val = ({v:last_formula.val, ixfe:last_formula.cell.ixfe, t:'s'}); | ||||
| 						temp_val = ({v:val, ixfe:last_formula.cell.ixfe, t:'s'}); | ||||
| 						temp_val.XF = XFs[temp_val.ixfe]; | ||||
| 						if(options.cellFormula) temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts); | ||||
| 						if(options.cellFormula) { | ||||
| 							temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts); | ||||
| 						} | ||||
| 						safe_format_xf(temp_val, options, wb.opts.Date1904); | ||||
| 						addcell(last_formula.cell, temp_val, options); | ||||
| 						last_formula = null; | ||||
| 					} | ||||
| 					} else throw new Error("String record expects Formula"); | ||||
| 				} break; | ||||
| 				case 'Array': { | ||||
| 					array_formulae.push(val); | ||||
| 					if(options.cellFormula && out[last_cell]) { | ||||
| 					var _arraystart = encode_cell(val[0].s); | ||||
| 					if(options.cellFormula && out[_arraystart]) { | ||||
| 						if(!last_formula) break; /* technically unreachable */ | ||||
| 						if(!last_cell || !out[last_cell]) break; /* technically unreachable */ | ||||
| 						out[last_cell].f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts); | ||||
| 						out[last_cell].F = encode_range(val[0]); | ||||
| 						if(!_arraystart || !out[_arraystart]) break; | ||||
| 						out[_arraystart].f = ""+stringify_formula(val[1], range, val[0], supbooks, opts); | ||||
| 						out[_arraystart].F = encode_range(val[0]); | ||||
| 					} | ||||
| 				} break; | ||||
| 				case 'ShrFmla': { | ||||
| @ -10895,6 +10939,7 @@ function parse_workbook(blob, options) { | ||||
| 					safe_format_xf(temp_val, options, wb.opts.Date1904); | ||||
| 					addcell({c:val.c, r:val.r}, temp_val, options); | ||||
| 					break; | ||||
| 
 | ||||
| 				case 'Dimensions': { | ||||
| 					if(file_depth === 1) range = val; /* TODO: stack */ | ||||
| 				} break; | ||||
| @ -12545,20 +12590,20 @@ function write_BIFF2LABEL(r, c, val) { | ||||
| } | ||||
| 
 | ||||
| function write_ws_biff_cell(ba, cell, R, C, opts) { | ||||
| 	switch(cell.t) { | ||||
| 	if(cell.v != null) switch(cell.t) { | ||||
| 		case 'n': | ||||
| 			if((cell.v == (cell.v|0)) && (cell.v >= 0) && (cell.v < 65536)) | ||||
| 				write_biff_rec(ba, 0x0002, write_BIFF2INT(R, C, cell.v)); | ||||
| 			else | ||||
| 				write_biff_rec(ba, 0x0003, write_BIFF2NUMBER(R,C, cell.v)); | ||||
| 			break; | ||||
| 		case 'b': case 'e': write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); break; | ||||
| 			return; | ||||
| 		case 'b': case 'e': write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); return; | ||||
| 		/* TODO: codepage, sst */ | ||||
| 		case 's': case 'str': | ||||
| 			write_biff_rec(ba, 0x0004, write_BIFF2LABEL(R, C, cell.v)); | ||||
| 			break; | ||||
| 		default: write_biff_rec(ba, 0x0001, write_BIFF2Cell(null, R, C)); | ||||
| 			return; | ||||
| 	} | ||||
| 	write_biff_rec(ba, 0x0001, write_BIFF2Cell(null, R, C)); | ||||
| } | ||||
| 
 | ||||
| function write_biff_ws(ba, ws, idx, opts, wb) { | ||||
| @ -12704,6 +12749,7 @@ var parse_content_xml = (function() { | ||||
| 					ctag = parsexmltag(Rn[0], false); | ||||
| 					q = ({t:ctag['数据类型'] || ctag['value-type'], v:null}); | ||||
| 					if(opts.cellFormula) { | ||||
| 						if(ctag.formula) ctag.formula = unescapexml(ctag.formula); | ||||
| 						if(ctag['number-matrix-columns-spanned'] && ctag['number-matrix-rows-spanned']) { | ||||
| 							mR = parseInt(ctag['number-matrix-rows-spanned'],10) || 0; | ||||
| 							mC = parseInt(ctag['number-matrix-columns-spanned'],10) || 0; | ||||
| @ -13051,11 +13097,22 @@ var write_content_xml = (function() { | ||||
| 				} | ||||
| 				if(skip) { o.push(covered_cell_xml); continue; } | ||||
| 				var ref = encode_cell({r:R, c:C}), cell = ws[ref]; | ||||
| 				var fmla = ""; | ||||
| 				if(cell && cell.f) { | ||||
| 					fmla = ' table:formula="' + escapexml(csf_to_ods_formula(cell.f)) + '"'; | ||||
| 					if(cell.F) { | ||||
| 						if(cell.F.substr(0, ref.length) == ref) { | ||||
| 							var _Fref = decode_range(cell.F); | ||||
| 							fmla += ' table:number-matrix-columns-spanned="' + (_Fref.e.c - _Fref.s.c + 1)+ '"'; | ||||
| 							fmla += ' table:number-matrix-rows-spanned="' + (_Fref.e.r - _Fref.s.r + 1) + '"'; | ||||
| 						} else fmla = ""; | ||||
| 					} | ||||
| 				} | ||||
| 				if(cell) switch(cell.t) { | ||||
| 					case 'b': o.push(cell_begin + mxml + vt + '"boolean" office:boolean-value="' + (cell.v ? 'true' : 'false') + '">' + p_begin + (cell.v ? 'TRUE' : 'FALSE') + p_end + cell_end); break; | ||||
| 					case 'n': o.push(cell_begin + mxml + vt + '"float" office:value="' + cell.v + '">' + p_begin + (cell.w||cell.v) + p_end + cell_end); break; | ||||
| 					case 's': case 'str': o.push(cell_begin + mxml + vt + '"string">' + p_begin + escapexml(cell.v) + p_end + cell_end); break; | ||||
| 					case 'd': o.push(cell_begin + mxml + vt + '"date" office:date-value="' + (new Date(cell.v).toISOString()) + '">' + p_begin + (cell.w||(new Date(cell.v).toISOString())) + p_end + cell_end); break; | ||||
| 					case 'b': o.push(cell_begin + mxml + vt + '"boolean" office:boolean-value="' + (cell.v ? 'true' : 'false') + '"' + fmla + '>' + p_begin + (cell.v ? 'TRUE' : 'FALSE') + p_end + cell_end); break; | ||||
| 					case 'n': o.push(cell_begin + mxml + vt + '"float" office:value="' + cell.v + '"' + fmla + '>' + p_begin + (cell.w||cell.v) + p_end + cell_end); break; | ||||
| 					case 's': case 'str': o.push(cell_begin + mxml + vt + '"string"' + fmla + '>' + p_begin + escapexml(cell.v) + p_end + cell_end); break; | ||||
| 					case 'd': o.push(cell_begin + mxml + vt + '"date" office:date-value="' + (new Date(cell.v).toISOString()) + '"' + fmla + '>' + p_begin + (cell.w||(new Date(cell.v).toISOString())) + p_end + cell_end); break; | ||||
| 					//case 'e':
 | ||||
| 					default: o.push(null_cell_xml); | ||||
| 				} else o.push(null_cell_xml); | ||||
| @ -13070,7 +13127,7 @@ var write_content_xml = (function() { | ||||
| 		var o = [XML_HEADER]; | ||||
| 		/* 3.1.3.2 */ | ||||
| 		if(opts.bookType == "fods") o.push('<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.spreadsheet">'); | ||||
| 		else o.push('<office:document-content office:version="1.2" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0">\n'); // TODO
 | ||||
| 		else o.push('<office:document-content office:version="1.2" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2">\n'); // TODO
 | ||||
| 		o.push('  <office:body>\n'); | ||||
| 		o.push('    <office:spreadsheet>\n'); | ||||
| 		for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts)); | ||||
| @ -13684,9 +13741,15 @@ function sheet_to_csv(sheet, opts) { | ||||
| 		rr = encode_row(R); | ||||
| 		for(C = r.s.c; C <= r.e.c; ++C) { | ||||
| 			val = sheet[cols[C] + rr]; | ||||
| 			txt = val !== undefined ? ''+format_cell(val) : ""; | ||||
| 			for(i = 0, cc = 0; i !== txt.length; ++i) if((cc = txt.charCodeAt(i)) === fs || cc === rs || cc === 34) { | ||||
| 				txt = "\"" + txt.replace(qreg, '""') + "\""; break; } | ||||
| 			if(val == null) txt = ""; | ||||
| 			else if(val.v != null) { | ||||
| 				txt = ''+format_cell(val); | ||||
| 				for(i = 0, cc = 0; i !== txt.length; ++i) if((cc = txt.charCodeAt(i)) === fs || cc === rs || cc === 34) { | ||||
| 					txt = "\"" + txt.replace(qreg, '""') + "\""; break; } | ||||
| 			} else if(val.f != null && !val.F) { | ||||
| 				txt = '=' + val.f; if(txt.indexOf(",") >= 0) txt = '"' + txt.replace(qreg, '""') + '"'; | ||||
| 			} else txt = ""; | ||||
| 			/* NOTE: Excel CSV does not support array formulae */ | ||||
| 			row += (C === r.s.c ? "" : FS) + txt; | ||||
| 		} | ||||
| 		out += row + RS; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user