| 
									
										
										
										
											2017-05-11 07:29:59 +00:00
										 |  |  | /* OpenDocument */ | 
					
						
							| 
									
										
										
										
											2022-03-11 05:29:05 +00:00
										 |  |  | var write_styles_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function() { | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 	var master_styles = [ | 
					
						
							|  |  |  | 		'<office:master-styles>', | 
					
						
							|  |  |  | 			'<style:master-page style:name="mp1" style:page-layout-name="mp1">', | 
					
						
							|  |  |  | 				'<style:header/>', | 
					
						
							|  |  |  | 				'<style:header-left style:display="false"/>', | 
					
						
							|  |  |  | 				'<style:footer/>', | 
					
						
							|  |  |  | 				'<style:footer-left style:display="false"/>', | 
					
						
							|  |  |  | 			'</style:master-page>', | 
					
						
							|  |  |  | 		'</office:master-styles>' | 
					
						
							|  |  |  | 	].join(""); | 
					
						
							| 
									
										
										
										
											2021-10-19 13:23:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-17 00:14:32 +00:00
										 |  |  | 	var payload = '<office:document-styles ' + wxt_helper({ | 
					
						
							|  |  |  | 		'xmlns:office':   "urn:oasis:names:tc:opendocument:xmlns:office:1.0", | 
					
						
							|  |  |  | 		'xmlns:table':    "urn:oasis:names:tc:opendocument:xmlns:table: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: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:number':   "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0", | 
					
						
							|  |  |  | 		'xmlns:svg':      "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0", | 
					
						
							|  |  |  | 		'xmlns:of':       "urn:oasis:names:tc:opendocument:xmlns:of:1.2", | 
					
						
							|  |  |  | 		'office:version': "1.2" | 
					
						
							| 
									
										
										
										
											2021-10-19 13:23:42 +00:00
										 |  |  | 	}) + '>' + master_styles + '</office:document-styles>'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-23 09:07:51 +00:00
										 |  |  | 	return function wso(/*::wb, opts*/) { | 
					
						
							| 
									
										
										
										
											2017-10-17 00:14:32 +00:00
										 |  |  | 		return XML_HEADER + payload; | 
					
						
							| 
									
										
										
										
											2017-05-11 07:29:59 +00:00
										 |  |  | 	}; | 
					
						
							|  |  |  | })(); | 
					
						
							| 
									
										
										
										
											2022-06-08 22:02:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | // TODO: find out if anyone actually read the spec.  LO has some wild errors
 | 
					
						
							|  |  |  | function write_number_format_ods(nf/*:string*/, nfidx/*:string*/)/*:string*/ { | 
					
						
							|  |  |  | 	var type = "number", payload = "", nopts = { "style:name": nfidx }, c = "", i = 0; | 
					
						
							|  |  |  | 	nf = nf.replace(/"[$]"/g, "$"); | 
					
						
							|  |  |  | 	/* TODO: replace with an actual parser based on a real grammar */ | 
					
						
							|  |  |  | 	j: { | 
					
						
							|  |  |  | 		// TODO: support style maps
 | 
					
						
							|  |  |  | 		if(nf.indexOf(";") > -1) { | 
					
						
							|  |  |  | 			console.error("Unsupported ODS Style Map exported.  Using first branch of " + nf); | 
					
						
							|  |  |  | 			nf = nf.slice(0, nf.indexOf(";")); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if(nf == "@") { type = "text"; payload = "<number:text-content/>"; break j; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* currency flag */ | 
					
						
							|  |  |  | 		if(nf.indexOf(/\$/) > -1) { type = "currency"; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* opening string literal */ | 
					
						
							|  |  |  | 		if(nf[i] == '"') { | 
					
						
							|  |  |  | 			c = ""; | 
					
						
							|  |  |  | 			while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i; | 
					
						
							|  |  |  | 			if(nf[i+1] == "*") { | 
					
						
							|  |  |  | 				i++; | 
					
						
							|  |  |  | 				payload += '<number:fill-character>' + escapexml(c.replace(/""/g, '"')) + '</number:fill-character>'; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				payload += '<number:text>' + escapexml(c.replace(/""/g, '"')) + '</number:text>'; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			nf = nf.slice(i+1); i = 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* fractions */ | 
					
						
							|  |  |  | 		var t = nf.match(/# (\?+)\/(\?+)/); | 
					
						
							|  |  |  | 		if(t) { payload += writextag("number:fraction", null, {"number:min-integer-digits":0, "number:min-numerator-digits": t[1].length, "number:max-denominator-value": Math.max(+(t[1].replace(/./g, "9")), +(t[2].replace(/./g, "9"))) }); break j; } | 
					
						
							|  |  |  | 		if((t=nf.match(/# (\?+)\/(\d+)/))) { payload += writextag("number:fraction", null, {"number:min-integer-digits":0, "number:min-numerator-digits": t[1].length, "number:denominator-value": +t[2]}); break j; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* percentages */ | 
					
						
							|  |  |  | 		if((t=nf.match(/(\d+)(|\.\d+)%/))) { type = "percentage"; payload += writextag("number:number", null, {"number:decimal-places": t[2] && t.length - 1 || 0, "number:min-decimal-places": t[2] && t.length - 1 || 0, "number:min-integer-digits": t[1].length }) + "<number:text>%</number:text>"; break j; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* datetime */ | 
					
						
							|  |  |  | 		var has_time = false; | 
					
						
							|  |  |  | 		if(["y","m","d"].indexOf(nf[0]) > -1) { | 
					
						
							|  |  |  | 			type = "date"; | 
					
						
							|  |  |  | 			k: for(; i < nf.length; ++i) switch((c = nf[i].toLowerCase())) { | 
					
						
							|  |  |  | 				case "h": case "s": has_time = true; --i; break k; | 
					
						
							|  |  |  | 				case "m": | 
					
						
							|  |  |  | 					l: for(var h = i+1; h < nf.length; ++h) switch(nf[h]) { | 
					
						
							|  |  |  | 						case "y": case "d": break l; | 
					
						
							|  |  |  | 						case "h": case "s": has_time = true; --i; break k; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					/* falls through */ | 
					
						
							|  |  |  | 				case "y": case "d": | 
					
						
							|  |  |  | 					while((nf[++i]||"").toLowerCase() == c[0]) c += c[0]; --i; | 
					
						
							|  |  |  | 					switch(c) { | 
					
						
							|  |  |  | 						case "y": case "yy": payload += "<number:year/>"; break; | 
					
						
							|  |  |  | 						case "yyy": case "yyyy": payload += '<number:year number:style="long"/>'; break; | 
					
						
							|  |  |  | 						case "mmmmm": console.error("ODS has no equivalent of format |mmmmm|"); | 
					
						
							|  |  |  | 							/* falls through */ | 
					
						
							|  |  |  | 						case "m": case "mm": case "mmm": case "mmmm": | 
					
						
							|  |  |  | 							payload += '<number:month number:style="' + (c.length % 2 ? "short" : "long") + '" number:textual="' + (c.length >= 3 ? "true" : "false") + '"/>'; | 
					
						
							|  |  |  | 							break; | 
					
						
							|  |  |  | 						case "d": case "dd": payload += '<number:day number:style="' + (c.length % 2 ? "short" : "long") + '"/>'; break; | 
					
						
							|  |  |  | 						case "ddd": case "dddd": payload += '<number:day-of-week number:style="' + (c.length % 2 ? "short" : "long") + '"/>'; break; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				case '"': | 
					
						
							|  |  |  | 					while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i; | 
					
						
							|  |  |  | 					payload += '<number:text>' + escapexml(c.slice(1).replace(/""/g, '"')) + '</number:text>'; | 
					
						
							|  |  |  | 					break; | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 				case '\\': c = nf[++i]; | 
					
						
							|  |  |  | 					payload += '<number:text>' + escapexml(c) + '</number:text>'; break; | 
					
						
							|  |  |  | 				case '/': case ':': payload += '<number:text>' + escapexml(c) + '</number:text>'; break; | 
					
						
							| 
									
										
										
										
											2022-06-08 22:02:17 +00:00
										 |  |  | 				default: console.error("unrecognized character " + c + " in ODF format " + nf); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if(!has_time) break j; | 
					
						
							|  |  |  | 			nf = nf.slice(i+1); i = 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if(nf.match(/^\[?[hms]/)) { | 
					
						
							|  |  |  | 			if(type == "number") type = "time"; | 
					
						
							|  |  |  | 			if(nf.match(/\[/)) { | 
					
						
							|  |  |  | 				nf = nf.replace(/[\[\]]/g, ""); | 
					
						
							|  |  |  | 				nopts['number:truncate-on-overflow'] = "false"; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			for(; i < nf.length; ++i) switch((c = nf[i].toLowerCase())) { | 
					
						
							|  |  |  | 				case "h": case "m": case "s": | 
					
						
							|  |  |  | 					while((nf[++i]||"").toLowerCase() == c[0]) c += c[0]; --i; | 
					
						
							|  |  |  | 					switch(c) { | 
					
						
							|  |  |  | 						case "h": case "hh": payload += '<number:hours number:style="' + (c.length % 2 ? "short" : "long") + '"/>'; break; | 
					
						
							|  |  |  | 						case "m": case "mm": payload += '<number:minutes number:style="' + (c.length % 2 ? "short" : "long") + '"/>'; break; | 
					
						
							|  |  |  | 						case "s": case "ss": | 
					
						
							|  |  |  | 							if(nf[i+1] == ".") do { c += nf[i+1]; ++i; } while(nf[i+1] == "0"); | 
					
						
							|  |  |  | 							payload += '<number:seconds number:style="' + (c.match("ss") ? "long" : "short") + '"' + (c.match(/\./) ? ' number:decimal-places="' + (c.match(/0+/)||[""])[0].length + '"' : "")+ '/>'; break; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				case '"': | 
					
						
							|  |  |  | 					while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i; | 
					
						
							|  |  |  | 					payload += '<number:text>' + escapexml(c.slice(1).replace(/""/g, '"')) + '</number:text>'; | 
					
						
							|  |  |  | 					break; | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 				case '/': case ':': payload += '<number:text>' + escapexml(c) + '</number:text>'; break; | 
					
						
							| 
									
										
										
										
											2022-06-08 22:02:17 +00:00
										 |  |  | 				case "a": | 
					
						
							|  |  |  | 					if(nf.slice(i, i+3).toLowerCase() == "a/p") { payload += '<number:am-pm/>'; i += 2; break; } // Note: ODF does not support A/P
 | 
					
						
							|  |  |  | 					if(nf.slice(i, i+5).toLowerCase() == "am/pm")  { payload += '<number:am-pm/>'; i += 4; break; } | 
					
						
							|  |  |  | 					/* falls through */ | 
					
						
							|  |  |  | 				default: console.error("unrecognized character " + c + " in ODF format " + nf); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break j; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* currency flag */ | 
					
						
							|  |  |  | 		if(nf.indexOf(/\$/) > -1) { type = "currency"; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* should be in a char loop */ | 
					
						
							|  |  |  | 		if(nf[0] == "$") { payload += '<number:currency-symbol number:language="en" number:country="US">$</number:currency-symbol>'; nf = nf.slice(1); i = 0; } | 
					
						
							|  |  |  | 		i = 0; if(nf[i] == '"') { | 
					
						
							|  |  |  | 			while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i; | 
					
						
							|  |  |  | 			if(nf[i+1] == "*") { | 
					
						
							|  |  |  | 				i++; | 
					
						
							|  |  |  | 				payload += '<number:fill-character>' + escapexml(c.replace(/""/g, '"')) + '</number:fill-character>'; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				payload += '<number:text>' + escapexml(c.replace(/""/g, '"')) + '</number:text>'; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			nf = nf.slice(i+1); i = 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* number TODO: interstitial text e.g. 000)000-0000 */ | 
					
						
							|  |  |  | 		var np = nf.match(/([#0][0#,]*)(\.[0#]*|)(E[+]?0*|)/i); | 
					
						
							|  |  |  | 		if(!np || !np[0]) console.error("Could not find numeric part of " + nf); | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			var base = np[1].replace(/,/g, ""); | 
					
						
							|  |  |  | 			payload += '<number:' + (np[3] ? "scientific-" : "")+ 'number' + | 
					
						
							|  |  |  | 				' number:min-integer-digits="' + (base.indexOf("0") == -1 ? "0" : base.length - base.indexOf("0")) + '"' + | 
					
						
							|  |  |  | 				(np[0].indexOf(",") > -1 ? ' number:grouping="true"' : "") + | 
					
						
							|  |  |  | 				(np[2] && ' number:decimal-places="' + (np[2].length - 1) + '"' || ' number:decimal-places="0"') + | 
					
						
							|  |  |  | 				(np[3] && np[3].indexOf("+") > -1 ? ' number:forced-exponent-sign="true"' : "" ) + | 
					
						
							|  |  |  | 				(np[3] ? ' number:min-exponent-digits="' + np[3].match(/0+/)[0].length + '"' : "" ) + | 
					
						
							|  |  |  | 				'>' + | 
					
						
							|  |  |  | 				/* TODO: interstitial text placeholders */ | 
					
						
							|  |  |  | 				'</number:' + (np[3] ? "scientific-" : "") + 'number>'; | 
					
						
							|  |  |  | 			i = np.index + np[0].length; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* residual text */ | 
					
						
							|  |  |  | 		if(nf[i] == '"') { | 
					
						
							|  |  |  | 			c = ""; | 
					
						
							|  |  |  | 			while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i; | 
					
						
							|  |  |  | 			payload += '<number:text>' + escapexml(c.replace(/""/g, '"')) + '</number:text>'; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(!payload) { console.error("Could not generate ODS number format for |" + nf + "|"); return ""; } | 
					
						
							|  |  |  | 	return writextag("number:" + type + "-style", payload, nopts); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-25 01:45:55 +00:00
										 |  |  | function write_names_ods(Names, SheetNames, idx) { | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 	//var scoped = Names.filter(function(name) { return name.Sheet == (idx == -1 ? null : idx); });
 | 
					
						
							|  |  |  | 	var scoped = []; for(var namei = 0; namei < Names.length; ++namei) { | 
					
						
							|  |  |  | 		var name = Names[namei]; | 
					
						
							|  |  |  | 		if(!name) continue; | 
					
						
							|  |  |  | 		if(name.Sheet == (idx == -1 ? null : idx)) scoped.push(name); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-05-25 01:45:55 +00:00
										 |  |  | 	if(!scoped.length) return ""; | 
					
						
							|  |  |  | 	return "      <table:named-expressions>\n" + scoped.map(function(name) { | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 		var odsref =  (idx == -1 ? "$" : "") + csf_to_ods_3D(name.Ref); | 
					
						
							| 
									
										
										
										
											2022-05-25 01:45:55 +00:00
										 |  |  | 		return "        " + writextag("table:named-range", null, { | 
					
						
							|  |  |  | 			"table:name": name.Name, | 
					
						
							|  |  |  | 			"table:cell-range-address": odsref, | 
					
						
							|  |  |  | 			"table:base-cell-address": odsref.replace(/[\.]?[^\.]*$/, ".$A$1") | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 	}).join("\n") + "\n      </table:named-expressions>\n"; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-03-11 05:29:05 +00:00
										 |  |  | var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function() { | 
					
						
							| 
									
										
										
										
											2017-10-17 00:14:32 +00:00
										 |  |  | 	/* 6.1.2 White Space Characters */ | 
					
						
							|  |  |  | 	var write_text_p = function(text/*:string*/)/*:string*/ { | 
					
						
							|  |  |  | 		return escapexml(text) | 
					
						
							|  |  |  | 			.replace(/  +/g, function($$){return '<text:s text:c="'+$$.length+'"/>';}) | 
					
						
							|  |  |  | 			.replace(/\t/g, "<text:tab/>") | 
					
						
							| 
									
										
										
										
											2021-09-13 06:02:38 +00:00
										 |  |  | 			.replace(/\n/g, "</text:p><text:p>") | 
					
						
							| 
									
										
										
										
											2017-10-17 00:14:32 +00:00
										 |  |  | 			.replace(/^ /, "<text:s/>").replace(/ $/, "<text:s/>"); | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-03 20:50:45 +00:00
										 |  |  | 	var null_cell_xml = '          <table:table-cell />\n'; | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 	var write_ws = function(ws, wb/*:Workbook*/, i/*:number*/, opts, nfs, date1904)/*:string*/ { | 
					
						
							| 
									
										
										
										
											2017-02-03 20:50:45 +00:00
										 |  |  | 		/* Section 9 Tables */ | 
					
						
							| 
									
										
										
										
											2017-12-30 05:40:35 +00:00
										 |  |  | 		var o/*:Array<string>*/ = []; | 
					
						
							| 
									
										
										
										
											2020-09-11 08:38:33 +00:00
										 |  |  | 		o.push('      <table:table table:name="' + escapexml(wb.SheetNames[i]) + '" table:style-name="ta1">\n'); | 
					
						
							| 
									
										
										
										
											2021-09-18 02:12:13 +00:00
										 |  |  | 		var R=0,C=0, range = decode_range(ws['!ref']||"A1"); | 
					
						
							| 
									
										
										
										
											2017-12-30 05:40:35 +00:00
										 |  |  | 		var marr/*:Array<Range>*/ = ws['!merges'] || [], mi = 0; | 
					
						
							| 
									
										
										
										
											2022-10-24 01:05:59 +00:00
										 |  |  | 		var dense = ws["!data"] != null; | 
					
						
							| 
									
										
										
										
											2021-09-30 07:28:03 +00:00
										 |  |  | 		if(ws["!cols"]) { | 
					
						
							|  |  |  | 			for(C = 0; C <= range.e.c; ++C) o.push('        <table:table-column' + (ws["!cols"][C] ? ' table:style-name="co' + ws["!cols"][C].ods + '"' : '') + '></table:table-column>\n'); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		var H = "", ROWS = ws["!rows"]||[]; | 
					
						
							|  |  |  | 		for(R = 0; R < range.s.r; ++R) { | 
					
						
							|  |  |  | 			H = ROWS[R] ? ' table:style-name="ro' + ROWS[R].ods + '"' : ""; | 
					
						
							|  |  |  | 			o.push('        <table:table-row' + H + '></table:table-row>\n'); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-02-03 20:50:45 +00:00
										 |  |  | 		for(; R <= range.e.r; ++R) { | 
					
						
							| 
									
										
										
										
											2021-09-30 07:28:03 +00:00
										 |  |  | 			H = ROWS[R] ? ' table:style-name="ro' + ROWS[R].ods + '"' : ""; | 
					
						
							|  |  |  | 			o.push('        <table:table-row' + H + '>\n'); | 
					
						
							| 
									
										
										
										
											2017-02-03 20:50:45 +00:00
										 |  |  | 			for(C=0; C < range.s.c; ++C) o.push(null_cell_xml); | 
					
						
							|  |  |  | 			for(; C <= range.e.c; ++C) { | 
					
						
							| 
									
										
										
										
											2017-04-30 16:27:03 +00:00
										 |  |  | 				var skip = false, ct = {}, textp = ""; | 
					
						
							| 
									
										
										
										
											2017-03-16 01:17:24 +00:00
										 |  |  | 				for(mi = 0; mi != marr.length; ++mi) { | 
					
						
							|  |  |  | 					if(marr[mi].s.c > C) continue; | 
					
						
							|  |  |  | 					if(marr[mi].s.r > R) continue; | 
					
						
							|  |  |  | 					if(marr[mi].e.c < C) continue; | 
					
						
							|  |  |  | 					if(marr[mi].e.r < R) continue; | 
					
						
							|  |  |  | 					if(marr[mi].s.c != C || marr[mi].s.r != R) skip = true; | 
					
						
							| 
									
										
										
										
											2017-04-30 16:27:03 +00:00
										 |  |  | 					ct['table:number-columns-spanned'] = (marr[mi].e.c - marr[mi].s.c + 1); | 
					
						
							|  |  |  | 					ct['table:number-rows-spanned'] =    (marr[mi].e.r - marr[mi].s.r + 1); | 
					
						
							| 
									
										
										
										
											2017-03-16 01:17:24 +00:00
										 |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2023-06-13 04:49:18 +00:00
										 |  |  | 				if(skip) { o.push('          <table:covered-table-cell/>\n'); continue; } | 
					
						
							| 
									
										
										
										
											2022-10-24 01:05:59 +00:00
										 |  |  | 				var ref = encode_cell({r:R, c:C}), cell = dense ? (ws["!data"][R]||[])[C]: ws[ref]; | 
					
						
							| 
									
										
										
										
											2017-03-18 00:45:06 +00:00
										 |  |  | 				if(cell && cell.f) { | 
					
						
							| 
									
										
										
										
											2017-04-30 16:27:03 +00:00
										 |  |  | 					ct['table:formula'] = escapexml(csf_to_ods_formula(cell.f)); | 
					
						
							| 
									
										
										
										
											2017-03-18 00:45:06 +00:00
										 |  |  | 					if(cell.F) { | 
					
						
							| 
									
										
										
										
											2018-01-11 08:01:25 +00:00
										 |  |  | 						if(cell.F.slice(0, ref.length) == ref) { | 
					
						
							| 
									
										
										
										
											2017-03-18 00:45:06 +00:00
										 |  |  | 							var _Fref = decode_range(cell.F); | 
					
						
							| 
									
										
										
										
											2017-04-30 16:27:03 +00:00
										 |  |  | 							ct['table:number-matrix-columns-spanned'] = (_Fref.e.c - _Fref.s.c + 1); | 
					
						
							|  |  |  | 							ct['table:number-matrix-rows-spanned'] =    (_Fref.e.r - _Fref.s.r + 1); | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2017-03-18 00:45:06 +00:00
										 |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2017-04-30 16:27:03 +00:00
										 |  |  | 				if(!cell) { o.push(null_cell_xml); continue; } | 
					
						
							|  |  |  | 				switch(cell.t) { | 
					
						
							|  |  |  | 					case 'b': | 
					
						
							|  |  |  | 						textp = (cell.v ? 'TRUE' : 'FALSE'); | 
					
						
							|  |  |  | 						ct['office:value-type'] = "boolean"; | 
					
						
							|  |  |  | 						ct['office:boolean-value'] = (cell.v ? 'true' : 'false'); | 
					
						
							|  |  |  | 						break; | 
					
						
							|  |  |  | 					case 'n': | 
					
						
							|  |  |  | 						textp = (cell.w||String(cell.v||0)); | 
					
						
							|  |  |  | 						ct['office:value-type'] = "float"; | 
					
						
							|  |  |  | 						ct['office:value'] = (cell.v||0); | 
					
						
							|  |  |  | 						break; | 
					
						
							|  |  |  | 					case 's': case 'str': | 
					
						
							| 
									
										
										
										
											2020-07-06 20:42:59 +00:00
										 |  |  | 						textp = cell.v == null ? "" : cell.v; | 
					
						
							| 
									
										
										
										
											2017-04-30 16:27:03 +00:00
										 |  |  | 						ct['office:value-type'] = "string"; | 
					
						
							|  |  |  | 						break; | 
					
						
							|  |  |  | 					case 'd': | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 						textp = (cell.w||(parseDate(cell.v, date1904).toISOString())); | 
					
						
							| 
									
										
										
										
											2017-04-30 16:27:03 +00:00
										 |  |  | 						ct['office:value-type'] = "date"; | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 						ct['office:date-value'] = (parseDate(cell.v, date1904).toISOString()); | 
					
						
							| 
									
										
										
										
											2017-04-30 16:27:03 +00:00
										 |  |  | 						ct['table:style-name'] = "ce1"; | 
					
						
							|  |  |  | 						break; | 
					
						
							| 
									
										
										
										
											2023-06-13 04:49:18 +00:00
										 |  |  | 					//case 'e': // TODO: translate to ODS errors
 | 
					
						
							|  |  |  | 					default: o.push(null_cell_xml); continue; // TODO: empty cell with comments
 | 
					
						
							| 
									
										
										
										
											2017-04-30 16:27:03 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2017-12-15 01:18:40 +00:00
										 |  |  | 				var text_p = write_text_p(textp); | 
					
						
							|  |  |  | 				if(cell.l && cell.l.Target) { | 
					
						
							| 
									
										
										
										
											2021-09-30 07:28:03 +00:00
										 |  |  | 					var _tgt = cell.l.Target; | 
					
						
							|  |  |  | 					_tgt = _tgt.charAt(0) == "#" ? "#" + csf_to_ods_3D(_tgt.slice(1)) : _tgt; | 
					
						
							|  |  |  | 					// TODO: choose correct parent path format based on link delimiters
 | 
					
						
							|  |  |  | 					if(_tgt.charAt(0) != "#" && !_tgt.match(/^\w+:/)) _tgt = '../' + _tgt; | 
					
						
							|  |  |  | 					text_p = writextag('text:a', text_p, {'xlink:href': _tgt.replace(/&/g, "&")}); | 
					
						
							| 
									
										
										
										
											2017-12-15 01:18:40 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2022-06-08 22:02:17 +00:00
										 |  |  | 				if(nfs[cell.z]) ct["table:style-name"] = "ce" + nfs[cell.z].slice(1); | 
					
						
							| 
									
										
										
										
											2023-06-13 04:49:18 +00:00
										 |  |  | 				var payload = writextag('text:p', text_p, {}); | 
					
						
							|  |  |  | 				if(cell.c) { | 
					
						
							|  |  |  | 					var acreator = "", apayload = "", aprops = {}; | 
					
						
							|  |  |  | 					for(var ci = 0; ci < cell.c.length; ++ci) { | 
					
						
							|  |  |  | 						if(!acreator && cell.c[ci].a) acreator = cell.c[ci].a; | 
					
						
							|  |  |  | 						apayload += "<text:p>" + write_text_p(cell.c[ci].t) + "</text:p>"; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					if(!cell.c.hidden) aprops["office:display"] = true; | 
					
						
							|  |  |  | 					payload = writextag('office:annotation', apayload, aprops) + payload; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				o.push('          ' + writextag('table:table-cell', payload, ct) + '\n'); | 
					
						
							| 
									
										
										
										
											2017-02-03 20:50:45 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			o.push('        </table:table-row>\n'); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2022-05-25 01:45:55 +00:00
										 |  |  | 		if((wb.Workbook||{}).Names) o.push(write_names_ods(wb.Workbook.Names, wb.SheetNames, i)); | 
					
						
							| 
									
										
										
										
											2017-02-03 20:50:45 +00:00
										 |  |  | 		o.push('      </table:table>\n'); | 
					
						
							|  |  |  | 		return o.join(""); | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-30 07:28:03 +00:00
										 |  |  | 	var write_automatic_styles_ods = function(o/*:Array<string>*/, wb) { | 
					
						
							| 
									
										
										
										
											2017-04-30 16:27:03 +00:00
										 |  |  | 		o.push(' <office:automatic-styles>\n'); | 
					
						
							| 
									
										
										
										
											2020-09-11 08:38:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-30 07:28:03 +00:00
										 |  |  | 		/* column styles */ | 
					
						
							|  |  |  | 		var cidx = 0; | 
					
						
							|  |  |  | 		wb.SheetNames.map(function(n) { return wb.Sheets[n]; }).forEach(function(ws) { | 
					
						
							|  |  |  | 			if(!ws) return; | 
					
						
							|  |  |  | 			if(ws["!cols"]) { | 
					
						
							|  |  |  | 				for(var C = 0; C < ws["!cols"].length; ++C) if(ws["!cols"][C]) { | 
					
						
							|  |  |  | 					var colobj = ws["!cols"][C]; | 
					
						
							|  |  |  | 					if(colobj.width == null && colobj.wpx == null && colobj.wch == null) continue; | 
					
						
							|  |  |  | 					process_col(colobj); | 
					
						
							|  |  |  | 					colobj.ods = cidx; | 
					
						
							|  |  |  | 					var w = ws["!cols"][C].wpx + "px"; | 
					
						
							|  |  |  | 					o.push('  <style:style style:name="co' + cidx + '" style:family="table-column">\n'); | 
					
						
							|  |  |  | 					o.push('   <style:table-column-properties fo:break-before="auto" style:column-width="' + w + '"/>\n'); | 
					
						
							|  |  |  | 					o.push('  </style:style>\n'); | 
					
						
							|  |  |  | 					++cidx; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* row styles */ | 
					
						
							|  |  |  | 		var ridx = 0; | 
					
						
							|  |  |  | 		wb.SheetNames.map(function(n) { return wb.Sheets[n]; }).forEach(function(ws) { | 
					
						
							|  |  |  | 			if(!ws) return; | 
					
						
							|  |  |  | 			if(ws["!rows"]) { | 
					
						
							|  |  |  | 				for(var R = 0; R < ws["!rows"].length; ++R) if(ws["!rows"][R]) { | 
					
						
							|  |  |  | 					ws["!rows"][R].ods = ridx; | 
					
						
							|  |  |  | 					var h = ws["!rows"][R].hpx + "px"; | 
					
						
							|  |  |  | 					o.push('  <style:style style:name="ro' + ridx + '" style:family="table-row">\n'); | 
					
						
							|  |  |  | 					o.push('   <style:table-row-properties fo:break-before="auto" style:row-height="' + h + '"/>\n'); | 
					
						
							|  |  |  | 					o.push('  </style:style>\n'); | 
					
						
							|  |  |  | 					++ridx; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-11 08:38:33 +00:00
										 |  |  | 		/* table */ | 
					
						
							| 
									
										
										
										
											2021-10-19 13:23:42 +00:00
										 |  |  | 		o.push('  <style:style style:name="ta1" style:family="table" style:master-page-name="mp1">\n'); | 
					
						
							| 
									
										
										
										
											2020-03-15 07:42:05 +00:00
										 |  |  | 		o.push('   <style:table-properties table:display="true" style:writing-mode="lr-tb"/>\n'); | 
					
						
							|  |  |  | 		o.push('  </style:style>\n'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-08 22:02:17 +00:00
										 |  |  | 		o.push('  <number:date-style style:name="N37" number:automatic-order="true">\n'); | 
					
						
							|  |  |  | 		o.push('   <number:month number:style="long"/>\n'); | 
					
						
							|  |  |  | 		o.push('   <number:text>/</number:text>\n'); | 
					
						
							|  |  |  | 		o.push('   <number:day number:style="long"/>\n'); | 
					
						
							|  |  |  | 		o.push('   <number:text>/</number:text>\n'); | 
					
						
							|  |  |  | 		o.push('   <number:year/>\n'); | 
					
						
							|  |  |  | 		o.push('  </number:date-style>\n'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* number formats, table cells, text */ | 
					
						
							|  |  |  | 		var nfs = {}; | 
					
						
							|  |  |  | 		var nfi = 69; | 
					
						
							|  |  |  | 		wb.SheetNames.map(function(n) { return wb.Sheets[n]; }).forEach(function(ws) { | 
					
						
							|  |  |  | 			if(!ws) return; | 
					
						
							| 
									
										
										
										
											2022-10-24 01:05:59 +00:00
										 |  |  | 			var dense = (ws["!data"] != null); | 
					
						
							| 
									
										
										
										
											2022-06-08 22:02:17 +00:00
										 |  |  | 			var range = decode_range(ws["!ref"]); | 
					
						
							|  |  |  | 			for(var R = 0; R <= range.e.r; ++R) for(var C = 0; C <= range.e.c; ++C) { | 
					
						
							| 
									
										
										
										
											2022-10-24 01:05:59 +00:00
										 |  |  | 				var c = dense ? (ws["!data"][R]||[])[C] : ws[encode_cell({r:R,c:C})]; | 
					
						
							| 
									
										
										
										
											2022-06-08 22:02:17 +00:00
										 |  |  | 				if(!c || !c.z || c.z.toLowerCase() == "general") continue; | 
					
						
							|  |  |  | 				if(!nfs[c.z]) { | 
					
						
							|  |  |  | 					var out = write_number_format_ods(c.z, "N" + nfi); | 
					
						
							|  |  |  | 					if(out) { nfs[c.z] = "N" + nfi; ++nfi; o.push(out + "\n"); } | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}); | 
					
						
							| 
									
										
										
										
											2017-04-30 16:27:03 +00:00
										 |  |  | 		o.push('  <style:style style:name="ce1" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N37"/>\n'); | 
					
						
							| 
									
										
										
										
											2022-06-08 22:02:17 +00:00
										 |  |  | 		keys(nfs).forEach(function(nf) { | 
					
						
							|  |  |  | 			o.push('<style:style style:name="ce' + nfs[nf].slice(1) + '" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="' + nfs[nf] + '"/>\n'); | 
					
						
							|  |  |  | 		}); | 
					
						
							| 
									
										
										
										
											2020-09-11 08:38:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* page-layout */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-30 16:27:03 +00:00
										 |  |  | 		o.push(' </office:automatic-styles>\n'); | 
					
						
							| 
									
										
										
										
											2022-06-08 22:02:17 +00:00
										 |  |  | 		return nfs; | 
					
						
							| 
									
										
										
										
											2017-04-30 16:27:03 +00:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-03 20:50:45 +00:00
										 |  |  | 	return function wcx(wb, opts) { | 
					
						
							|  |  |  | 		var o = [XML_HEADER]; | 
					
						
							|  |  |  | 		/* 3.1.3.2 */ | 
					
						
							| 
									
										
										
										
											2017-04-30 16:27:03 +00:00
										 |  |  | 		var attr = wxt_helper({ | 
					
						
							|  |  |  | 			'xmlns:office':       "urn:oasis:names:tc:opendocument:xmlns:office:1.0", | 
					
						
							|  |  |  | 			'xmlns:table':        "urn:oasis:names:tc:opendocument:xmlns:table: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: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: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:sheet':        "urn:oasis:names:tc:opendocument:sh33tjs:1.0", | 
					
						
							|  |  |  | 			'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" | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		var fods = wxt_helper({ | 
					
						
							| 
									
										
										
										
											2017-10-17 00:14:32 +00:00
										 |  |  | 			'xmlns:config':    "urn:oasis:names:tc:opendocument:xmlns:config:1.0", | 
					
						
							|  |  |  | 			'office:mimetype': "application/vnd.oasis.opendocument.spreadsheet" | 
					
						
							| 
									
										
										
										
											2017-04-30 16:27:03 +00:00
										 |  |  | 		}); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-30 07:28:03 +00:00
										 |  |  | 		if(opts.bookType == "fods") { | 
					
						
							|  |  |  | 			o.push('<office:document' + attr + fods + '>\n'); | 
					
						
							| 
									
										
										
										
											2022-06-08 22:02:17 +00:00
										 |  |  | 			o.push(write_meta_ods().replace(/<office:document-meta.*?>/, "").replace(/<\/office:document-meta>/, "") + "\n"); | 
					
						
							| 
									
										
										
										
											2021-09-30 07:28:03 +00:00
										 |  |  | 			// TODO: settings (equiv of settings.xml for ODS)
 | 
					
						
							|  |  |  | 		} else o.push('<office:document-content' + attr  + '>\n'); | 
					
						
							|  |  |  | 		// o.push('  <office:scripts/>\n');
 | 
					
						
							| 
									
										
										
										
											2022-06-08 22:02:17 +00:00
										 |  |  | 		var nfs = write_automatic_styles_ods(o, wb); | 
					
						
							| 
									
										
										
										
											2017-02-03 20:50:45 +00:00
										 |  |  | 		o.push('  <office:body>\n'); | 
					
						
							|  |  |  | 		o.push('    <office:spreadsheet>\n'); | 
					
						
							| 
									
										
										
										
											2022-06-06 23:05:27 +00:00
										 |  |  | 		if(((wb.Workbook||{}).WBProps||{}).date1904) o.push('      <table:calculation-settings table:case-sensitive="false" table:search-criteria-must-apply-to-whole-cell="true" table:use-wildcards="true" table:use-regular-expressions="false" table:automatic-find-labels="false">\n        <table:null-date table:date-value="1904-01-01"/>\n      </table:calculation-settings>\n'); | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 		for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts, nfs, ((wb.Workbook||{}).WBProps||{}).date1904)); | 
					
						
							| 
									
										
										
										
											2022-05-25 01:45:55 +00:00
										 |  |  | 		if((wb.Workbook||{}).Names) o.push(write_names_ods(wb.Workbook.Names, wb.SheetNames, -1)); | 
					
						
							| 
									
										
										
										
											2017-02-03 20:50:45 +00:00
										 |  |  | 		o.push('    </office:spreadsheet>\n'); | 
					
						
							|  |  |  | 		o.push('  </office:body>\n'); | 
					
						
							| 
									
										
										
										
											2017-02-22 06:57:59 +00:00
										 |  |  | 		if(opts.bookType == "fods") o.push('</office:document>'); | 
					
						
							|  |  |  | 		else o.push('</office:document-content>'); | 
					
						
							| 
									
										
										
										
											2017-02-03 20:50:45 +00:00
										 |  |  | 		return o.join(""); | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | })(); | 
					
						
							| 
									
										
										
										
											2017-05-11 07:29:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | function write_ods(wb/*:any*/, opts/*:any*/) { | 
					
						
							|  |  |  | 	if(opts.bookType == "fods") return write_content_ods(wb, opts); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-04 19:50:49 +00:00
										 |  |  | 	var zip = zip_new(); | 
					
						
							| 
									
										
										
										
											2017-05-11 07:29:59 +00:00
										 |  |  | 	var f = ""; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var manifest/*:Array<Array<string> >*/ = []; | 
					
						
							| 
									
										
										
										
											2017-12-30 05:40:35 +00:00
										 |  |  | 	var rdf/*:Array<[string, string]>*/ = []; | 
					
						
							| 
									
										
										
										
											2017-05-11 07:29:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-17 00:14:32 +00:00
										 |  |  | 	/* Part 3 Section 3.3 MIME Media Type */ | 
					
						
							| 
									
										
										
										
											2017-05-11 07:29:59 +00:00
										 |  |  | 	f = "mimetype"; | 
					
						
							| 
									
										
										
										
											2019-08-04 19:50:49 +00:00
										 |  |  | 	zip_add_file(zip, f, "application/vnd.oasis.opendocument.spreadsheet"); | 
					
						
							| 
									
										
										
										
											2017-05-11 07:29:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Part 1 Section 2.2 Documents */ | 
					
						
							|  |  |  | 	f = "content.xml"; | 
					
						
							| 
									
										
										
										
											2019-08-04 19:50:49 +00:00
										 |  |  | 	zip_add_file(zip, f, write_content_ods(wb, opts)); | 
					
						
							| 
									
										
										
										
											2017-05-11 07:29:59 +00:00
										 |  |  | 	manifest.push([f, "text/xml"]); | 
					
						
							|  |  |  | 	rdf.push([f, "ContentFile"]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* TODO: these are hard-coded styles to satiate excel */ | 
					
						
							|  |  |  | 	f = "styles.xml"; | 
					
						
							| 
									
										
										
										
											2019-08-04 19:50:49 +00:00
										 |  |  | 	zip_add_file(zip, f, write_styles_ods(wb, opts)); | 
					
						
							| 
									
										
										
										
											2017-05-11 07:29:59 +00:00
										 |  |  | 	manifest.push([f, "text/xml"]); | 
					
						
							|  |  |  | 	rdf.push([f, "StylesFile"]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* TODO: this is hard-coded to satiate excel */ | 
					
						
							|  |  |  | 	f = "meta.xml"; | 
					
						
							| 
									
										
										
										
											2021-09-30 07:28:03 +00:00
										 |  |  | 	zip_add_file(zip, f, XML_HEADER + write_meta_ods(/*::wb, opts*/)); | 
					
						
							| 
									
										
										
										
											2017-05-11 07:29:59 +00:00
										 |  |  | 	manifest.push([f, "text/xml"]); | 
					
						
							|  |  |  | 	rdf.push([f, "MetadataFile"]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-17 00:14:32 +00:00
										 |  |  | 	/* Part 3 Section 6 Metadata Manifest File */ | 
					
						
							|  |  |  | 	f = "manifest.rdf"; | 
					
						
							| 
									
										
										
										
											2019-08-04 19:50:49 +00:00
										 |  |  | 	zip_add_file(zip, f, write_rdf(rdf/*, opts*/)); | 
					
						
							| 
									
										
										
										
											2017-10-17 00:14:32 +00:00
										 |  |  | 	manifest.push([f, "application/rdf+xml"]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-11 07:29:59 +00:00
										 |  |  | 	/* Part 3 Section 4 Manifest File */ | 
					
						
							|  |  |  | 	f = "META-INF/manifest.xml"; | 
					
						
							| 
									
										
										
										
											2019-08-04 19:50:49 +00:00
										 |  |  | 	zip_add_file(zip, f, write_manifest(manifest/*, opts*/)); | 
					
						
							| 
									
										
										
										
											2017-05-11 07:29:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return zip; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 |