forked from sheetjs/sheetjs
		
	more format parity
- XLS/XLSX/XLSB/XML/ODS cellFormula option + test - XLS/XLSX/XLSB/XML/ODS cellText option + test - XML document property order - XML write margins + protection - removed gitbook search
This commit is contained in:
		
							parent
							
								
									83ec60688f
								
							
						
					
					
						commit
						95a377c0e4
					
				| @ -12,6 +12,8 @@ enhancements and additional features by request. | ||||
| 
 | ||||
| [**Commercial Support**](http://sheetjs.com/support) | ||||
| 
 | ||||
| [**Rendered Documentation**](https://sheetjs.gitbooks.io/docs/) | ||||
| 
 | ||||
| [**In-Browser Demos**](http://sheetjs.com/demos) | ||||
| 
 | ||||
| [**Source Code**](http://git.io/xlsx) | ||||
| @ -634,8 +636,9 @@ In addition to the base sheet keys, worksheets also add: | ||||
|   the first cell (upper-left) in the range is set. | ||||
| 
 | ||||
| - `ws['protect']`: object of write sheet protection properties.  The `password` | ||||
|   key specifies the password.  The writer uses the XOR obfuscation method.  The | ||||
|   following keys control the sheet protection (same as ECMA-376 18.3.1.85): | ||||
|   key specifies the password for formats that support password-protected sheets | ||||
|   (XLSX/XLSB/XLS).  The writer uses the XOR obfuscation method.  The following | ||||
|   keys control the sheet protection (same as ECMA-376 18.3.1.85): | ||||
| 
 | ||||
| | key                   | functionality disabled if value is true              | | ||||
| |:----------------------|:-----------------------------------------------------| | ||||
| @ -659,7 +662,7 @@ In addition to the base sheet keys, worksheets also add: | ||||
| 
 | ||||
| ```typescript | ||||
| type AutoFilter = { | ||||
| 	ref:string; // A-1 based range representing the AutoFilter table range | ||||
|   ref:string; // A-1 based range representing the AutoFilter table range | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
|  | ||||
| @ -1,25 +1,35 @@ | ||||
| /* Common Name -> XLML Name */ | ||||
| var XLMLDocPropsMap = { | ||||
| 	Category: 'Category', | ||||
| 	ContentStatus: 'ContentStatus', /* NOTE: missing from schema */ | ||||
| 	Keywords: 'Keywords', | ||||
| 	LastAuthor: 'LastAuthor', | ||||
| 	LastPrinted: 'LastPrinted', | ||||
| 	RevNumber: 'Revision', | ||||
| 	Author: 'Author', | ||||
| 	Comments: 'Description', | ||||
| 	Identifier: 'Identifier', /* NOTE: missing from schema */ | ||||
| 	Language: 'Language', /* NOTE: missing from schema */ | ||||
| 	Subject: 'Subject', | ||||
| 	Title: 'Title', | ||||
| 	Subject: 'Subject', | ||||
| 	Author: 'Author', | ||||
| 	Keywords: 'Keywords', | ||||
| 	Comments: 'Description', | ||||
| 	LastAuthor: 'LastAuthor', | ||||
| 	RevNumber: 'Revision', | ||||
| 	Application: 'AppName', | ||||
| 	/* TotalTime: 'TotalTime', */ | ||||
| 	LastPrinted: 'LastPrinted', | ||||
| 	CreatedDate: 'Created', | ||||
| 	ModifiedDate: 'LastSaved', | ||||
| 
 | ||||
| 	Application: 'AppName', | ||||
| 	AppVersion: 'Version', | ||||
| 	TotalTime: 'TotalTime', | ||||
| 	/* Pages */ | ||||
| 	/* Words */ | ||||
| 	/* Characters */ | ||||
| 	Category: 'Category', | ||||
| 	/* PresentationFormat */ | ||||
| 	Manager: 'Manager', | ||||
| 	Company: 'Company' | ||||
| 	Company: 'Company', | ||||
| 	/* Guid */ | ||||
| 	/* HyperlinkBase */ | ||||
| 	/* Bytes */ | ||||
| 	/* Lines */ | ||||
| 	/* Paragraphs */ | ||||
| 	/* CharactersWithSpaces */ | ||||
| 	AppVersion: 'Version', | ||||
| 
 | ||||
| 	ContentStatus: 'ContentStatus', /* NOTE: missing from schema */ | ||||
| 	Identifier: 'Identifier', /* NOTE: missing from schema */ | ||||
| 	Language: 'Language' /* NOTE: missing from schema */ | ||||
| }; | ||||
| var evert_XLMLDPM = evert(XLMLDocPropsMap); | ||||
| 
 | ||||
| @ -28,19 +38,21 @@ function xlml_set_prop(Props, tag/*:string*/, val) { | ||||
| 	Props[tag] = val; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* TODO: verify */ | ||||
| function xlml_write_docprops(Props, opts) { | ||||
| 	var o = []; | ||||
| 	CORE_PROPS.concat(EXT_PROPS).forEach(function(p) { | ||||
| 	keys(XLMLDocPropsMap).map(function(m) { | ||||
| 		for(var i = 0; i < CORE_PROPS.length; ++i) if(CORE_PROPS[i][1] == m) return CORE_PROPS[i]; | ||||
| 		for(i = 0; i < EXT_PROPS.length; ++i) if(EXT_PROPS[i][1] == m) return EXT_PROPS[i]; | ||||
| 		throw m; | ||||
| 	}).forEach(function(p) { | ||||
| 		if(Props[p[1]] == null) return; | ||||
| 		var m = opts && opts.Props && opts.Props[p[1]] != null ? opts.Props[p[1]] : Props[p[1]]; | ||||
| 		switch(p[2]) { | ||||
| 			case 'date': m = new Date(m).toISOString(); break; | ||||
| 			case 'date': m = new Date(m).toISOString().replace(/\.\d*Z/,"Z"); break; | ||||
| 		} | ||||
| 		if(typeof m == 'number') m = String(m); | ||||
| 		else if(m === true || m === false) { m = m ? "1" : "0"; } | ||||
| 		else if(m instanceof Date) m = new Date(m).toISOString(); | ||||
| 		else if(m instanceof Date) m = new Date(m).toISOString().replace(/\.\d*Z/,""); | ||||
| 		o.push(writetag(XLMLDocPropsMap[p[1]] || p[1], m)); | ||||
| 	}); | ||||
| 	return writextag('DocumentProperties', o.join(""), {xmlns:XLMLNS.o }); | ||||
|  | ||||
| @ -244,8 +244,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) { | ||||
| 		/* 18.3.1.73 row CT_Row */ | ||||
| 		for(ri = 0; ri < xlen; ++ri) if(x.charCodeAt(ri) === 62) break; ++ri; | ||||
| 		tag = parsexmltag(x.substr(0,ri), true); | ||||
| 		/* SpreadSheetGear uses implicit r/c */ | ||||
| 		tagr = typeof tag.r !== 'undefined' ? parseInt(tag.r, 10) : tagr+1; tagc = -1; | ||||
| 		tagr = tag.r != null ? parseInt(tag.r, 10) : tagr+1; tagc = -1; | ||||
| 		if(opts.sheetRows && opts.sheetRows < tagr) continue; | ||||
| 		if(guess.s.r > tagr - 1) guess.s.r = tagr - 1; | ||||
| 		if(guess.e.r < tagr - 1) guess.e.r = tagr - 1; | ||||
| @ -297,7 +296,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) { | ||||
| 							p.F = arrayf[i][1]; | ||||
| 			} | ||||
| 
 | ||||
| 			if(tag.t === undefined && p.v === undefined) { | ||||
| 			if(tag.t == null && p.v === undefined) { | ||||
| 				if(!opts.sheetStubs) continue; | ||||
| 				p.t = "z"; | ||||
| 			} | ||||
| @ -335,7 +334,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) { | ||||
| 					break; | ||||
| 				/* error string in .w, number in .v */ | ||||
| 				case 'e': | ||||
| 					if(opts && opts.cellText === false) p.w = p.v; | ||||
| 					if(!opts || opts.cellText !== false) p.w = p.v; | ||||
| 					p.v = RBErr[p.v]; break; | ||||
| 			} | ||||
| 			/* formatting */ | ||||
|  | ||||
| @ -400,7 +400,7 @@ function parse_ws_bin(data, _opts, rels, wb, themes, styles)/*:Worksheet*/ { | ||||
| 					case 'n': p.v = val[1]; break; | ||||
| 					case 's': sstr = strs[val[1]]; p.v = sstr.t; p.r = sstr.r; break; | ||||
| 					case 'b': p.v = val[1] ? true : false; break; | ||||
| 					case 'e': p.v = val[1]; p.w = BErr[p.v]; break; | ||||
| 					case 'e': p.v = val[1]; if(opts.cellText !== false) p.w = BErr[p.v]; break; | ||||
| 					case 'str': p.t = 's'; p.v = utf8read(val[1]); break; | ||||
| 				} | ||||
| 				if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.ifmt,null,opts, themes, styles); | ||||
|  | ||||
| @ -121,11 +121,11 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, a | ||||
| 			if(cell.v === undefined) cell.v=+xml; | ||||
| 			if(!cell.t) cell.t = 'n'; | ||||
| 			break; | ||||
| 		case 'Error': cell.t = 'e'; cell.v = RBErr[xml]; cell.w = xml; break; | ||||
| 		case 'Error': cell.t = 'e'; cell.v = RBErr[xml]; if(o.cellText !== false) cell.w = xml; break; | ||||
| 		default: cell.t = 's'; cell.v = xlml_fixstr(ss||xml); break; | ||||
| 	} | ||||
| 	safe_format_xlml(cell, nf, o); | ||||
| 	if(o.cellFormula != null) { | ||||
| 	if(o.cellFormula !== false) { | ||||
| 		if(cell.Formula) { | ||||
| 			var fstr = unescapexml(cell.Formula); | ||||
| 			/* strictly speaking, the leading = is required but some writers omit */ | ||||
| @ -837,17 +837,107 @@ function write_sty_xlml(wb, opts)/*:string*/ { | ||||
| } | ||||
| /* WorksheetOptions */ | ||||
| function write_ws_xlml_wsopts(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/)/*:string*/ { | ||||
| 	if(!ws) return ""; | ||||
| 	var o = []; | ||||
| 	/* NOTE: spec technically allows any order, but stick with implied order */ | ||||
| 
 | ||||
| 	/* FitToPage */ | ||||
| 	/* DoNotDisplayColHeaders */ | ||||
| 	/* DoNotDisplayRowHeaders */ | ||||
| 	/* ViewableRange */ | ||||
| 	/* Selection */ | ||||
| 	/* GridlineColor */ | ||||
| 	/* Name */ | ||||
| 	/* ExcelWorksheetType */ | ||||
| 	/* IntlMacro */ | ||||
| 	/* Unsynced */ | ||||
| 	/* Selected */ | ||||
| 	/* CodeName */ | ||||
| 
 | ||||
| 	if(ws['!margins']) { | ||||
| 		o.push("<PageSetup>"); | ||||
| 		if(ws['!margins'].header) o.push(writextag("Header", null, {'x:Margin':ws['!margins'].header})); | ||||
| 		if(ws['!margins'].footer) o.push(writextag("Footer", null, {'x:Margin':ws['!margins'].footer})); | ||||
| 		o.push(writextag("PageMargins", null, { | ||||
| 			'x:Bottom': ws['!margins'].bottom || "0.75", | ||||
| 			'x:Left': ws['!margins'].left || "0.7", | ||||
| 			'x:Right': ws['!margins'].right || "0.7", | ||||
| 			'x:Top': ws['!margins'].top || "0.75" | ||||
| 		})); | ||||
| 		o.push("</PageSetup>"); | ||||
| 	} | ||||
| 
 | ||||
| 	/* PageSetup */ | ||||
| 	/* DisplayPageBreak */ | ||||
| 	/* TransitionExpressionEvaluation */ | ||||
| 	/* TransitionFormulaEntry */ | ||||
| 	/* Print */ | ||||
| 	/* Zoom */ | ||||
| 	/* PageLayoutZoom */ | ||||
| 	/* PageBreakZoom */ | ||||
| 	/* ShowPageBreakZoom */ | ||||
| 	/* DefaultRowHeight */ | ||||
| 	/* DefaultColumnWidth */ | ||||
| 	/* StandardWidth */ | ||||
| 
 | ||||
| 	if(wb && wb.Workbook && wb.Workbook.Sheets && wb.Workbook.Sheets[idx]) { | ||||
| 		/* Visible */ | ||||
| 		if(!!wb.Workbook.Sheets[idx].Hidden) o.push("<Visible>" + (wb.Workbook.Sheets[idx].Hidden == 1 ? "SheetHidden" : "SheetVeryHidden") + "</Visible>"); | ||||
| 		if(!!wb.Workbook.Sheets[idx].Hidden) o.push(writextag("Visible", (wb.Workbook.Sheets[idx].Hidden == 1 ? "SheetHidden" : "SheetVeryHidden"), {})); | ||||
| 		else { | ||||
| 			/* Selected */ | ||||
| 			for(var i = 0; i < idx; ++i) if(wb.Workbook.Sheets[i] && !wb.Workbook.Sheets[i].Hidden) break; | ||||
| 			if(i == idx) o.push("<Selected/>"); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* LeftColumnVisible */ | ||||
| 	/* DisplayRightToLeft */ | ||||
| 	/* GridlineColorIndex */ | ||||
| 	/* DisplayFormulas */ | ||||
| 	/* DoNotDisplayGridlines */ | ||||
| 	/* DoNotDisplayHeadings */ | ||||
| 	/* DoNotDisplayOutline */ | ||||
| 	/* ApplyAutomaticOutlineStyles */ | ||||
| 	/* NoSummaryRowsBelowDetail */ | ||||
| 	/* NoSummaryColumnsRightDetail */ | ||||
| 	/* DoNotDisplayZeros */ | ||||
| 	/* ActiveRow */ | ||||
| 	/* ActiveColumn */ | ||||
| 	/* FilterOn */ | ||||
| 	/* RangeSelection */ | ||||
| 	/* TopRowVisible */ | ||||
| 	/* TopRowBottomPane */ | ||||
| 	/* LeftColumnRightPane */ | ||||
| 	/* ActivePane */ | ||||
| 	/* SplitHorizontal */ | ||||
| 	/* SplitVertical */ | ||||
| 	/* FreezePanes */ | ||||
| 	/* FrozenNoSplit */ | ||||
| 	/* TabColorIndex */ | ||||
| 	/* Panes */ | ||||
| 
 | ||||
| 	/* NOTE: Password not supported in XLML Format */ | ||||
| 	if(ws['!protect']) { | ||||
| 		o.push(writetag("ProtectContents", "True")); | ||||
| 		if(ws['!protect'].objects) o.push(writetag("ProtectObjects", "True")); | ||||
| 		if(ws['!protect'].scenarios) o.push(writetag("ProtectScenarios", "True")); | ||||
| 		if(ws['!protect'].selectLockedCells != null && !ws['!protect'].selectLockedCells) o.push(writetag("EnableSelection", "NoSelection")); | ||||
| 		else if(ws['!protect'].selectUnlockedCells != null && !ws['!protect'].selectUnlockedCells) o.push(writetag("EnableSelection", "UnlockedCells")); | ||||
| 	[ | ||||
| 		[ "formatColumns", "AllowFormatCells" ], | ||||
| 		[ "formatRows", "AllowSizeCols" ], | ||||
| 		[ "formatCells", "AllowSizeRows" ], | ||||
| 		[ "insertColumns", "AllowInsertCols" ], | ||||
| 		[ "insertRows", "AllowInsertRows" ], | ||||
| 		[ "insertHyperlinks", "AllowInsertHyperlinks" ], | ||||
| 		[ "deleteColumns", "AllowDeleteCols" ], | ||||
| 		[ "deleteRows", "AllowDeleteRows" ], | ||||
| 		[ "sort", "AllowSort" ], | ||||
| 		[ "autoFilter", "AllowFilter" ], | ||||
| 		[ "pivotTables", "AllowUsePivotTables" ] | ||||
| 	].forEach(function(x) { if(ws['!protect'][x[0]]) o.push("<"+x[1]+"/>"); }); | ||||
| 	} | ||||
| 
 | ||||
| 	if(o.length == 0) return ""; | ||||
| 	return writextag("WorksheetOptions", o.join(""), {xmlns:XLMLNS.x}); | ||||
| } | ||||
|  | ||||
| @ -54,12 +54,13 @@ function slurp(R, blob, length/*:number*/, opts) { | ||||
| 
 | ||||
| function safe_format_xf(p/*:any*/, opts/*:ParseOpts*/, date1904/*:?boolean*/) { | ||||
| 	if(p.t === 'z') return; | ||||
| 	if(p.t === 'e') { p.w = p.w || BErr[p.v]; } | ||||
| 	if(!p.XF) return; | ||||
| 	try { | ||||
| 		var fmtid = p.XF.ifmt||0; | ||||
| 		if(opts.cellNF) p.z = SSF._table[fmtid]; | ||||
| 		if(p.t === 'e'){} | ||||
| 	} catch(e) { if(opts.WTF) throw e; } | ||||
| 	if(!opts || opts.cellText !== false) try { | ||||
| 		if(p.t === 'e') { p.w = p.w || BErr[p.v]; } | ||||
| 		else if(fmtid === 0) { | ||||
| 			if(p.t === 'n') { | ||||
| 				if((p.v|0) === p.v) p.w = SSF._general_int(p.v); | ||||
|  | ||||
| @ -135,7 +135,7 @@ var parse_content_xml = (function() { | ||||
| 						isstub = textpidx == 0; | ||||
| 					} | ||||
| 					if(comments.length > 0) { q.c = comments; comments = []; } | ||||
| 					if(textp) q.w = textp; | ||||
| 					if(textp && opts.cellText !== false) q.w = textp; | ||||
| 					if(!isstub || opts.sheetStubs) { | ||||
| 						if(!(opts.sheetRows && opts.sheetRows < R)) { | ||||
| 							if(opts.dense) { | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
| 	"title": "SheetJS js-xlsx", | ||||
| 	"author": "sheetjs", | ||||
| 	"gitbook": "3.2.2", | ||||
| 	"plugins": ["anchorjs", "ga", "sidebar-ad", "-sharing", "advanced-emoji"], | ||||
| 	"plugins": ["anchorjs", "ga", "sidebar-ad", "-sharing", "-search", "advanced-emoji"], | ||||
| 	"pluginsConfig": { | ||||
| 		"anchorjs": { | ||||
| 			"icon": "#", | ||||
|  | ||||
| @ -12,6 +12,8 @@ enhancements and additional features by request. | ||||
| 
 | ||||
| [**Commercial Support**](http://sheetjs.com/support) | ||||
| 
 | ||||
| [**Rendered Documentation**](https://sheetjs.gitbooks.io/docs/) | ||||
| 
 | ||||
| [**In-Browser Demos**](http://sheetjs.com/demos) | ||||
| 
 | ||||
| [**Source Code**](http://git.io/xlsx) | ||||
|  | ||||
| @ -14,8 +14,9 @@ In addition to the base sheet keys, worksheets also add: | ||||
|   the first cell (upper-left) in the range is set. | ||||
| 
 | ||||
| - `ws['protect']`: object of write sheet protection properties.  The `password` | ||||
|   key specifies the password.  The writer uses the XOR obfuscation method.  The | ||||
|   following keys control the sheet protection (same as ECMA-376 18.3.1.85): | ||||
|   key specifies the password for formats that support password-protected sheets | ||||
|   (XLSX/XLSB/XLS).  The writer uses the XOR obfuscation method.  The following | ||||
|   keys control the sheet protection (same as ECMA-376 18.3.1.85): | ||||
| 
 | ||||
| | key                   | functionality disabled if value is true              | | ||||
| |:----------------------|:-----------------------------------------------------| | ||||
| @ -39,7 +40,7 @@ In addition to the base sheet keys, worksheets also add: | ||||
| 
 | ||||
| ```typescript | ||||
| type AutoFilter = { | ||||
| 	ref:string; // A-1 based range representing the AutoFilter table range | ||||
|   ref:string; // A-1 based range representing the AutoFilter table range | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										33
									
								
								test.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										33
									
								
								test.js
									
									
									
									
									
								
							| @ -284,6 +284,7 @@ describe('parse options', function() { | ||||
| 	if(typeof before != 'undefined') before(bef); | ||||
| 	else it('before', bef); | ||||
| 	describe('cell', function() { | ||||
| 		var FSTPaths = [paths.fstxls, paths.fstxml, paths.fstxlsx, paths.fstxlsb, paths.fstods]; | ||||
| 		it('XLSX should generate HTML by default', function() { | ||||
| 			var wb = X.readFile(paths.cstxlsx); | ||||
| 			var ws = wb.Sheets.Sheet1; | ||||
| @ -299,7 +300,7 @@ describe('parse options', function() { | ||||
| 			}); | ||||
| 		}); | ||||
| 		it('should generate formulae by default', function() { | ||||
| 			[paths.fstxls, paths.fstxlsb].forEach(function(p) { | ||||
| 			FSTPaths.forEach(function(p) { | ||||
| 				var wb = X.readFile(p); | ||||
| 				var found = false; | ||||
| 				wb.SheetNames.forEach(function(s) { | ||||
| @ -312,7 +313,7 @@ describe('parse options', function() { | ||||
| 			}); | ||||
| 		}); | ||||
| 		it('should not generate formulae when requested', function() { | ||||
| 			[paths.fstxls, paths.fstxlsb].forEach(function(p) { | ||||
| 			FSTPaths.forEach(function(p) { | ||||
| 				var wb =X.readFile(p,{cellFormula:false}); | ||||
| 				wb.SheetNames.forEach(function(s) { | ||||
| 					var ws = wb.Sheets[s]; | ||||
| @ -322,6 +323,30 @@ describe('parse options', function() { | ||||
| 				}); | ||||
| 			}); | ||||
| 		}); | ||||
| 		it('should generate formatted text by default', function() { | ||||
| 			FSTPaths.forEach(function(p) { | ||||
| 				var wb = X.readFile(p); | ||||
| 				var found = false; | ||||
| 				wb.SheetNames.forEach(function(s) { | ||||
| 					var ws = wb.Sheets[s]; | ||||
| 					each_cell(ws, function(cell) { | ||||
| 						if(typeof cell.w !== 'undefined') return (found = true); | ||||
| 					}); | ||||
| 				}); | ||||
| 				assert(found); | ||||
| 			}); | ||||
| 		}); | ||||
| 		it('should not generate formatted text when requested', function() { | ||||
| 			FSTPaths.forEach(function(p) { | ||||
| 				var wb =X.readFile(p,{cellText:false}); | ||||
| 				wb.SheetNames.forEach(function(s) { | ||||
| 					var ws = wb.Sheets[s]; | ||||
| 					each_cell(ws, function(cell) { | ||||
| 						assert(typeof cell.w === 'undefined'); | ||||
| 					}); | ||||
| 				}); | ||||
| 			}); | ||||
| 		}); | ||||
| 		it('should not generate number formats by default', function() { | ||||
| 			[paths.nfxls, paths.nfxlsx, paths.nfxlsb].forEach(function(p) { | ||||
| 				var wb = X.readFile(p); | ||||
| @ -1218,7 +1243,7 @@ describe('roundtrip features', function() { | ||||
| 
 | ||||
| 				if(m[0].t === 'n' && m[1].t === 'n') assert.equal(m[0].v, m[1].v); | ||||
| 				else if(m[0].t === 'd' && m[1].t === 'd') assert.equal(m[0].v.toString(), m[1].v.toString()); | ||||
| 				else if(m[1].t === 'n') assert(Math.abs(datenum(new Date(m[0].v)) - m[1].v) < 0.01); /* TODO: 1sec adjustment */ | ||||
| 				else if(m[1].t === 'n') assert(Math.abs(datenum(new Date(m[0].v)) - m[1].v) < 0.01); | ||||
| 			}); | ||||
| 		}); | ||||
| 	}); | ||||
| @ -1253,7 +1278,7 @@ describe('roundtrip features', function() { | ||||
| 	}); | ||||
| 
 | ||||
| 	(fs.existsSync(paths.pmxlsx) ? describe : describe.skip)('should preserve page margins', function() {[ | ||||
| 			//['xlml', paths.pmxml],
 | ||||
| 			['xlml', paths.pmxml], | ||||
| 			['xlsx', paths.pmxlsx], | ||||
| 			['xlsb', paths.pmxlsb] | ||||
| 		].forEach(function(w) { it(w[0], function() { | ||||
|  | ||||
							
								
								
									
										166
									
								
								xlsx.flow.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										166
									
								
								xlsx.flow.js
									
									
									
									
									
								
							| @ -3330,26 +3330,36 @@ function write_cust_props(cp, opts)/*:string*/ { | ||||
| } | ||||
| /* Common Name -> XLML Name */ | ||||
| var XLMLDocPropsMap = { | ||||
| 	Category: 'Category', | ||||
| 	ContentStatus: 'ContentStatus', /* NOTE: missing from schema */ | ||||
| 	Keywords: 'Keywords', | ||||
| 	LastAuthor: 'LastAuthor', | ||||
| 	LastPrinted: 'LastPrinted', | ||||
| 	RevNumber: 'Revision', | ||||
| 	Author: 'Author', | ||||
| 	Comments: 'Description', | ||||
| 	Identifier: 'Identifier', /* NOTE: missing from schema */ | ||||
| 	Language: 'Language', /* NOTE: missing from schema */ | ||||
| 	Subject: 'Subject', | ||||
| 	Title: 'Title', | ||||
| 	Subject: 'Subject', | ||||
| 	Author: 'Author', | ||||
| 	Keywords: 'Keywords', | ||||
| 	Comments: 'Description', | ||||
| 	LastAuthor: 'LastAuthor', | ||||
| 	RevNumber: 'Revision', | ||||
| 	Application: 'AppName', | ||||
| 	/* TotalTime: 'TotalTime', */ | ||||
| 	LastPrinted: 'LastPrinted', | ||||
| 	CreatedDate: 'Created', | ||||
| 	ModifiedDate: 'LastSaved', | ||||
| 
 | ||||
| 	Application: 'AppName', | ||||
| 	AppVersion: 'Version', | ||||
| 	TotalTime: 'TotalTime', | ||||
| 	/* Pages */ | ||||
| 	/* Words */ | ||||
| 	/* Characters */ | ||||
| 	Category: 'Category', | ||||
| 	/* PresentationFormat */ | ||||
| 	Manager: 'Manager', | ||||
| 	Company: 'Company' | ||||
| 	Company: 'Company', | ||||
| 	/* Guid */ | ||||
| 	/* HyperlinkBase */ | ||||
| 	/* Bytes */ | ||||
| 	/* Lines */ | ||||
| 	/* Paragraphs */ | ||||
| 	/* CharactersWithSpaces */ | ||||
| 	AppVersion: 'Version', | ||||
| 
 | ||||
| 	ContentStatus: 'ContentStatus', /* NOTE: missing from schema */ | ||||
| 	Identifier: 'Identifier', /* NOTE: missing from schema */ | ||||
| 	Language: 'Language' /* NOTE: missing from schema */ | ||||
| }; | ||||
| var evert_XLMLDPM = evert(XLMLDocPropsMap); | ||||
| 
 | ||||
| @ -3358,19 +3368,21 @@ function xlml_set_prop(Props, tag/*:string*/, val) { | ||||
| 	Props[tag] = val; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* TODO: verify */ | ||||
| function xlml_write_docprops(Props, opts) { | ||||
| 	var o = []; | ||||
| 	CORE_PROPS.concat(EXT_PROPS).forEach(function(p) { | ||||
| 	keys(XLMLDocPropsMap).map(function(m) { | ||||
| 		for(var i = 0; i < CORE_PROPS.length; ++i) if(CORE_PROPS[i][1] == m) return CORE_PROPS[i]; | ||||
| 		for(i = 0; i < EXT_PROPS.length; ++i) if(EXT_PROPS[i][1] == m) return EXT_PROPS[i]; | ||||
| 		throw m; | ||||
| 	}).forEach(function(p) { | ||||
| 		if(Props[p[1]] == null) return; | ||||
| 		var m = opts && opts.Props && opts.Props[p[1]] != null ? opts.Props[p[1]] : Props[p[1]]; | ||||
| 		switch(p[2]) { | ||||
| 			case 'date': m = new Date(m).toISOString(); break; | ||||
| 			case 'date': m = new Date(m).toISOString().replace(/\.\d*Z/,"Z"); break; | ||||
| 		} | ||||
| 		if(typeof m == 'number') m = String(m); | ||||
| 		else if(m === true || m === false) { m = m ? "1" : "0"; } | ||||
| 		else if(m instanceof Date) m = new Date(m).toISOString(); | ||||
| 		else if(m instanceof Date) m = new Date(m).toISOString().replace(/\.\d*Z/,""); | ||||
| 		o.push(writetag(XLMLDocPropsMap[p[1]] || p[1], m)); | ||||
| 	}); | ||||
| 	return writextag('DocumentProperties', o.join(""), {xmlns:XLMLNS.o }); | ||||
| @ -10228,8 +10240,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) { | ||||
| 		/* 18.3.1.73 row CT_Row */ | ||||
| 		for(ri = 0; ri < xlen; ++ri) if(x.charCodeAt(ri) === 62) break; ++ri; | ||||
| 		tag = parsexmltag(x.substr(0,ri), true); | ||||
| 		/* SpreadSheetGear uses implicit r/c */ | ||||
| 		tagr = typeof tag.r !== 'undefined' ? parseInt(tag.r, 10) : tagr+1; tagc = -1; | ||||
| 		tagr = tag.r != null ? parseInt(tag.r, 10) : tagr+1; tagc = -1; | ||||
| 		if(opts.sheetRows && opts.sheetRows < tagr) continue; | ||||
| 		if(guess.s.r > tagr - 1) guess.s.r = tagr - 1; | ||||
| 		if(guess.e.r < tagr - 1) guess.e.r = tagr - 1; | ||||
| @ -10281,7 +10292,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) { | ||||
| 							p.F = arrayf[i][1]; | ||||
| 			} | ||||
| 
 | ||||
| 			if(tag.t === undefined && p.v === undefined) { | ||||
| 			if(tag.t == null && p.v === undefined) { | ||||
| 				if(!opts.sheetStubs) continue; | ||||
| 				p.t = "z"; | ||||
| 			} | ||||
| @ -10319,7 +10330,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) { | ||||
| 					break; | ||||
| 				/* error string in .w, number in .v */ | ||||
| 				case 'e': | ||||
| 					if(opts && opts.cellText === false) p.w = p.v; | ||||
| 					if(!opts || opts.cellText !== false) p.w = p.v; | ||||
| 					p.v = RBErr[p.v]; break; | ||||
| 			} | ||||
| 			/* formatting */ | ||||
| @ -10881,7 +10892,7 @@ function parse_ws_bin(data, _opts, rels, wb, themes, styles)/*:Worksheet*/ { | ||||
| 					case 'n': p.v = val[1]; break; | ||||
| 					case 's': sstr = strs[val[1]]; p.v = sstr.t; p.r = sstr.r; break; | ||||
| 					case 'b': p.v = val[1] ? true : false; break; | ||||
| 					case 'e': p.v = val[1]; p.w = BErr[p.v]; break; | ||||
| 					case 'e': p.v = val[1]; if(opts.cellText !== false) p.w = BErr[p.v]; break; | ||||
| 					case 'str': p.t = 's'; p.v = utf8read(val[1]); break; | ||||
| 				} | ||||
| 				if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.ifmt,null,opts, themes, styles); | ||||
| @ -12145,11 +12156,11 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, a | ||||
| 			if(cell.v === undefined) cell.v=+xml; | ||||
| 			if(!cell.t) cell.t = 'n'; | ||||
| 			break; | ||||
| 		case 'Error': cell.t = 'e'; cell.v = RBErr[xml]; cell.w = xml; break; | ||||
| 		case 'Error': cell.t = 'e'; cell.v = RBErr[xml]; if(o.cellText !== false) cell.w = xml; break; | ||||
| 		default: cell.t = 's'; cell.v = xlml_fixstr(ss||xml); break; | ||||
| 	} | ||||
| 	safe_format_xlml(cell, nf, o); | ||||
| 	if(o.cellFormula != null) { | ||||
| 	if(o.cellFormula !== false) { | ||||
| 		if(cell.Formula) { | ||||
| 			var fstr = unescapexml(cell.Formula); | ||||
| 			/* strictly speaking, the leading = is required but some writers omit */ | ||||
| @ -12861,17 +12872,107 @@ function write_sty_xlml(wb, opts)/*:string*/ { | ||||
| } | ||||
| /* WorksheetOptions */ | ||||
| function write_ws_xlml_wsopts(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/)/*:string*/ { | ||||
| 	if(!ws) return ""; | ||||
| 	var o = []; | ||||
| 	/* NOTE: spec technically allows any order, but stick with implied order */ | ||||
| 
 | ||||
| 	/* FitToPage */ | ||||
| 	/* DoNotDisplayColHeaders */ | ||||
| 	/* DoNotDisplayRowHeaders */ | ||||
| 	/* ViewableRange */ | ||||
| 	/* Selection */ | ||||
| 	/* GridlineColor */ | ||||
| 	/* Name */ | ||||
| 	/* ExcelWorksheetType */ | ||||
| 	/* IntlMacro */ | ||||
| 	/* Unsynced */ | ||||
| 	/* Selected */ | ||||
| 	/* CodeName */ | ||||
| 
 | ||||
| 	if(ws['!margins']) { | ||||
| 		o.push("<PageSetup>"); | ||||
| 		if(ws['!margins'].header) o.push(writextag("Header", null, {'x:Margin':ws['!margins'].header})); | ||||
| 		if(ws['!margins'].footer) o.push(writextag("Footer", null, {'x:Margin':ws['!margins'].footer})); | ||||
| 		o.push(writextag("PageMargins", null, { | ||||
| 			'x:Bottom': ws['!margins'].bottom || "0.75", | ||||
| 			'x:Left': ws['!margins'].left || "0.7", | ||||
| 			'x:Right': ws['!margins'].right || "0.7", | ||||
| 			'x:Top': ws['!margins'].top || "0.75" | ||||
| 		})); | ||||
| 		o.push("</PageSetup>"); | ||||
| 	} | ||||
| 
 | ||||
| 	/* PageSetup */ | ||||
| 	/* DisplayPageBreak */ | ||||
| 	/* TransitionExpressionEvaluation */ | ||||
| 	/* TransitionFormulaEntry */ | ||||
| 	/* Print */ | ||||
| 	/* Zoom */ | ||||
| 	/* PageLayoutZoom */ | ||||
| 	/* PageBreakZoom */ | ||||
| 	/* ShowPageBreakZoom */ | ||||
| 	/* DefaultRowHeight */ | ||||
| 	/* DefaultColumnWidth */ | ||||
| 	/* StandardWidth */ | ||||
| 
 | ||||
| 	if(wb && wb.Workbook && wb.Workbook.Sheets && wb.Workbook.Sheets[idx]) { | ||||
| 		/* Visible */ | ||||
| 		if(!!wb.Workbook.Sheets[idx].Hidden) o.push("<Visible>" + (wb.Workbook.Sheets[idx].Hidden == 1 ? "SheetHidden" : "SheetVeryHidden") + "</Visible>"); | ||||
| 		if(!!wb.Workbook.Sheets[idx].Hidden) o.push(writextag("Visible", (wb.Workbook.Sheets[idx].Hidden == 1 ? "SheetHidden" : "SheetVeryHidden"), {})); | ||||
| 		else { | ||||
| 			/* Selected */ | ||||
| 			for(var i = 0; i < idx; ++i) if(wb.Workbook.Sheets[i] && !wb.Workbook.Sheets[i].Hidden) break; | ||||
| 			if(i == idx) o.push("<Selected/>"); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* LeftColumnVisible */ | ||||
| 	/* DisplayRightToLeft */ | ||||
| 	/* GridlineColorIndex */ | ||||
| 	/* DisplayFormulas */ | ||||
| 	/* DoNotDisplayGridlines */ | ||||
| 	/* DoNotDisplayHeadings */ | ||||
| 	/* DoNotDisplayOutline */ | ||||
| 	/* ApplyAutomaticOutlineStyles */ | ||||
| 	/* NoSummaryRowsBelowDetail */ | ||||
| 	/* NoSummaryColumnsRightDetail */ | ||||
| 	/* DoNotDisplayZeros */ | ||||
| 	/* ActiveRow */ | ||||
| 	/* ActiveColumn */ | ||||
| 	/* FilterOn */ | ||||
| 	/* RangeSelection */ | ||||
| 	/* TopRowVisible */ | ||||
| 	/* TopRowBottomPane */ | ||||
| 	/* LeftColumnRightPane */ | ||||
| 	/* ActivePane */ | ||||
| 	/* SplitHorizontal */ | ||||
| 	/* SplitVertical */ | ||||
| 	/* FreezePanes */ | ||||
| 	/* FrozenNoSplit */ | ||||
| 	/* TabColorIndex */ | ||||
| 	/* Panes */ | ||||
| 
 | ||||
| 	/* NOTE: Password not supported in XLML Format */ | ||||
| 	if(ws['!protect']) { | ||||
| 		o.push(writetag("ProtectContents", "True")); | ||||
| 		if(ws['!protect'].objects) o.push(writetag("ProtectObjects", "True")); | ||||
| 		if(ws['!protect'].scenarios) o.push(writetag("ProtectScenarios", "True")); | ||||
| 		if(ws['!protect'].selectLockedCells != null && !ws['!protect'].selectLockedCells) o.push(writetag("EnableSelection", "NoSelection")); | ||||
| 		else if(ws['!protect'].selectUnlockedCells != null && !ws['!protect'].selectUnlockedCells) o.push(writetag("EnableSelection", "UnlockedCells")); | ||||
| 	[ | ||||
| 		[ "formatColumns", "AllowFormatCells" ], | ||||
| 		[ "formatRows", "AllowSizeCols" ], | ||||
| 		[ "formatCells", "AllowSizeRows" ], | ||||
| 		[ "insertColumns", "AllowInsertCols" ], | ||||
| 		[ "insertRows", "AllowInsertRows" ], | ||||
| 		[ "insertHyperlinks", "AllowInsertHyperlinks" ], | ||||
| 		[ "deleteColumns", "AllowDeleteCols" ], | ||||
| 		[ "deleteRows", "AllowDeleteRows" ], | ||||
| 		[ "sort", "AllowSort" ], | ||||
| 		[ "autoFilter", "AllowFilter" ], | ||||
| 		[ "pivotTables", "AllowUsePivotTables" ] | ||||
| 	].forEach(function(x) { if(ws['!protect'][x[0]]) o.push("<"+x[1]+"/>"); }); | ||||
| 	} | ||||
| 
 | ||||
| 	if(o.length == 0) return ""; | ||||
| 	return writextag("WorksheetOptions", o.join(""), {xmlns:XLMLNS.x}); | ||||
| } | ||||
| @ -13048,12 +13149,13 @@ function slurp(R, blob, length/*:number*/, opts) { | ||||
| 
 | ||||
| function safe_format_xf(p/*:any*/, opts/*:ParseOpts*/, date1904/*:?boolean*/) { | ||||
| 	if(p.t === 'z') return; | ||||
| 	if(p.t === 'e') { p.w = p.w || BErr[p.v]; } | ||||
| 	if(!p.XF) return; | ||||
| 	try { | ||||
| 		var fmtid = p.XF.ifmt||0; | ||||
| 		if(opts.cellNF) p.z = SSF._table[fmtid]; | ||||
| 		if(p.t === 'e'){} | ||||
| 	} catch(e) { if(opts.WTF) throw e; } | ||||
| 	if(!opts || opts.cellText !== false) try { | ||||
| 		if(p.t === 'e') { p.w = p.w || BErr[p.v]; } | ||||
| 		else if(fmtid === 0) { | ||||
| 			if(p.t === 'n') { | ||||
| 				if((p.v|0) === p.v) p.w = SSF._general_int(p.v); | ||||
| @ -15436,7 +15538,7 @@ var parse_content_xml = (function() { | ||||
| 						isstub = textpidx == 0; | ||||
| 					} | ||||
| 					if(comments.length > 0) { q.c = comments; comments = []; } | ||||
| 					if(textp) q.w = textp; | ||||
| 					if(textp && opts.cellText !== false) q.w = textp; | ||||
| 					if(!isstub || opts.sheetStubs) { | ||||
| 						if(!(opts.sheetRows && opts.sheetRows < R)) { | ||||
| 							if(opts.dense) { | ||||
|  | ||||
							
								
								
									
										166
									
								
								xlsx.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										166
									
								
								xlsx.js
									
									
									
									
									
								
							| @ -3271,26 +3271,36 @@ function write_cust_props(cp, opts) { | ||||
| } | ||||
| /* Common Name -> XLML Name */ | ||||
| var XLMLDocPropsMap = { | ||||
| 	Category: 'Category', | ||||
| 	ContentStatus: 'ContentStatus', /* NOTE: missing from schema */ | ||||
| 	Keywords: 'Keywords', | ||||
| 	LastAuthor: 'LastAuthor', | ||||
| 	LastPrinted: 'LastPrinted', | ||||
| 	RevNumber: 'Revision', | ||||
| 	Author: 'Author', | ||||
| 	Comments: 'Description', | ||||
| 	Identifier: 'Identifier', /* NOTE: missing from schema */ | ||||
| 	Language: 'Language', /* NOTE: missing from schema */ | ||||
| 	Subject: 'Subject', | ||||
| 	Title: 'Title', | ||||
| 	Subject: 'Subject', | ||||
| 	Author: 'Author', | ||||
| 	Keywords: 'Keywords', | ||||
| 	Comments: 'Description', | ||||
| 	LastAuthor: 'LastAuthor', | ||||
| 	RevNumber: 'Revision', | ||||
| 	Application: 'AppName', | ||||
| 	/* TotalTime: 'TotalTime', */ | ||||
| 	LastPrinted: 'LastPrinted', | ||||
| 	CreatedDate: 'Created', | ||||
| 	ModifiedDate: 'LastSaved', | ||||
| 
 | ||||
| 	Application: 'AppName', | ||||
| 	AppVersion: 'Version', | ||||
| 	TotalTime: 'TotalTime', | ||||
| 	/* Pages */ | ||||
| 	/* Words */ | ||||
| 	/* Characters */ | ||||
| 	Category: 'Category', | ||||
| 	/* PresentationFormat */ | ||||
| 	Manager: 'Manager', | ||||
| 	Company: 'Company' | ||||
| 	Company: 'Company', | ||||
| 	/* Guid */ | ||||
| 	/* HyperlinkBase */ | ||||
| 	/* Bytes */ | ||||
| 	/* Lines */ | ||||
| 	/* Paragraphs */ | ||||
| 	/* CharactersWithSpaces */ | ||||
| 	AppVersion: 'Version', | ||||
| 
 | ||||
| 	ContentStatus: 'ContentStatus', /* NOTE: missing from schema */ | ||||
| 	Identifier: 'Identifier', /* NOTE: missing from schema */ | ||||
| 	Language: 'Language' /* NOTE: missing from schema */ | ||||
| }; | ||||
| var evert_XLMLDPM = evert(XLMLDocPropsMap); | ||||
| 
 | ||||
| @ -3299,19 +3309,21 @@ function xlml_set_prop(Props, tag, val) { | ||||
| 	Props[tag] = val; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* TODO: verify */ | ||||
| function xlml_write_docprops(Props, opts) { | ||||
| 	var o = []; | ||||
| 	CORE_PROPS.concat(EXT_PROPS).forEach(function(p) { | ||||
| 	keys(XLMLDocPropsMap).map(function(m) { | ||||
| 		for(var i = 0; i < CORE_PROPS.length; ++i) if(CORE_PROPS[i][1] == m) return CORE_PROPS[i]; | ||||
| 		for(i = 0; i < EXT_PROPS.length; ++i) if(EXT_PROPS[i][1] == m) return EXT_PROPS[i]; | ||||
| 		throw m; | ||||
| 	}).forEach(function(p) { | ||||
| 		if(Props[p[1]] == null) return; | ||||
| 		var m = opts && opts.Props && opts.Props[p[1]] != null ? opts.Props[p[1]] : Props[p[1]]; | ||||
| 		switch(p[2]) { | ||||
| 			case 'date': m = new Date(m).toISOString(); break; | ||||
| 			case 'date': m = new Date(m).toISOString().replace(/\.\d*Z/,"Z"); break; | ||||
| 		} | ||||
| 		if(typeof m == 'number') m = String(m); | ||||
| 		else if(m === true || m === false) { m = m ? "1" : "0"; } | ||||
| 		else if(m instanceof Date) m = new Date(m).toISOString(); | ||||
| 		else if(m instanceof Date) m = new Date(m).toISOString().replace(/\.\d*Z/,""); | ||||
| 		o.push(writetag(XLMLDocPropsMap[p[1]] || p[1], m)); | ||||
| 	}); | ||||
| 	return writextag('DocumentProperties', o.join(""), {xmlns:XLMLNS.o }); | ||||
| @ -10166,8 +10178,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) { | ||||
| 		/* 18.3.1.73 row CT_Row */ | ||||
| 		for(ri = 0; ri < xlen; ++ri) if(x.charCodeAt(ri) === 62) break; ++ri; | ||||
| 		tag = parsexmltag(x.substr(0,ri), true); | ||||
| 		/* SpreadSheetGear uses implicit r/c */ | ||||
| 		tagr = typeof tag.r !== 'undefined' ? parseInt(tag.r, 10) : tagr+1; tagc = -1; | ||||
| 		tagr = tag.r != null ? parseInt(tag.r, 10) : tagr+1; tagc = -1; | ||||
| 		if(opts.sheetRows && opts.sheetRows < tagr) continue; | ||||
| 		if(guess.s.r > tagr - 1) guess.s.r = tagr - 1; | ||||
| 		if(guess.e.r < tagr - 1) guess.e.r = tagr - 1; | ||||
| @ -10219,7 +10230,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) { | ||||
| 							p.F = arrayf[i][1]; | ||||
| 			} | ||||
| 
 | ||||
| 			if(tag.t === undefined && p.v === undefined) { | ||||
| 			if(tag.t == null && p.v === undefined) { | ||||
| 				if(!opts.sheetStubs) continue; | ||||
| 				p.t = "z"; | ||||
| 			} | ||||
| @ -10257,7 +10268,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) { | ||||
| 					break; | ||||
| 				/* error string in .w, number in .v */ | ||||
| 				case 'e': | ||||
| 					if(opts && opts.cellText === false) p.w = p.v; | ||||
| 					if(!opts || opts.cellText !== false) p.w = p.v; | ||||
| 					p.v = RBErr[p.v]; break; | ||||
| 			} | ||||
| 			/* formatting */ | ||||
| @ -10819,7 +10830,7 @@ function parse_ws_bin(data, _opts, rels, wb, themes, styles) { | ||||
| 					case 'n': p.v = val[1]; break; | ||||
| 					case 's': sstr = strs[val[1]]; p.v = sstr.t; p.r = sstr.r; break; | ||||
| 					case 'b': p.v = val[1] ? true : false; break; | ||||
| 					case 'e': p.v = val[1]; p.w = BErr[p.v]; break; | ||||
| 					case 'e': p.v = val[1]; if(opts.cellText !== false) p.w = BErr[p.v]; break; | ||||
| 					case 'str': p.t = 's'; p.v = utf8read(val[1]); break; | ||||
| 				} | ||||
| 				if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.ifmt,null,opts, themes, styles); | ||||
| @ -12081,11 +12092,11 @@ function parse_xlml_data(xml, ss, data, cell, base, styles, csty, row, arrayf, o | ||||
| 			if(cell.v === undefined) cell.v=+xml; | ||||
| 			if(!cell.t) cell.t = 'n'; | ||||
| 			break; | ||||
| 		case 'Error': cell.t = 'e'; cell.v = RBErr[xml]; cell.w = xml; break; | ||||
| 		case 'Error': cell.t = 'e'; cell.v = RBErr[xml]; if(o.cellText !== false) cell.w = xml; break; | ||||
| 		default: cell.t = 's'; cell.v = xlml_fixstr(ss||xml); break; | ||||
| 	} | ||||
| 	safe_format_xlml(cell, nf, o); | ||||
| 	if(o.cellFormula != null) { | ||||
| 	if(o.cellFormula !== false) { | ||||
| 		if(cell.Formula) { | ||||
| 			var fstr = unescapexml(cell.Formula); | ||||
| 			/* strictly speaking, the leading = is required but some writers omit */ | ||||
| @ -12795,17 +12806,107 @@ function write_sty_xlml(wb, opts) { | ||||
| } | ||||
| /* WorksheetOptions */ | ||||
| function write_ws_xlml_wsopts(ws, opts, idx, wb) { | ||||
| 	if(!ws) return ""; | ||||
| 	var o = []; | ||||
| 	/* NOTE: spec technically allows any order, but stick with implied order */ | ||||
| 
 | ||||
| 	/* FitToPage */ | ||||
| 	/* DoNotDisplayColHeaders */ | ||||
| 	/* DoNotDisplayRowHeaders */ | ||||
| 	/* ViewableRange */ | ||||
| 	/* Selection */ | ||||
| 	/* GridlineColor */ | ||||
| 	/* Name */ | ||||
| 	/* ExcelWorksheetType */ | ||||
| 	/* IntlMacro */ | ||||
| 	/* Unsynced */ | ||||
| 	/* Selected */ | ||||
| 	/* CodeName */ | ||||
| 
 | ||||
| 	if(ws['!margins']) { | ||||
| 		o.push("<PageSetup>"); | ||||
| 		if(ws['!margins'].header) o.push(writextag("Header", null, {'x:Margin':ws['!margins'].header})); | ||||
| 		if(ws['!margins'].footer) o.push(writextag("Footer", null, {'x:Margin':ws['!margins'].footer})); | ||||
| 		o.push(writextag("PageMargins", null, { | ||||
| 			'x:Bottom': ws['!margins'].bottom || "0.75", | ||||
| 			'x:Left': ws['!margins'].left || "0.7", | ||||
| 			'x:Right': ws['!margins'].right || "0.7", | ||||
| 			'x:Top': ws['!margins'].top || "0.75" | ||||
| 		})); | ||||
| 		o.push("</PageSetup>"); | ||||
| 	} | ||||
| 
 | ||||
| 	/* PageSetup */ | ||||
| 	/* DisplayPageBreak */ | ||||
| 	/* TransitionExpressionEvaluation */ | ||||
| 	/* TransitionFormulaEntry */ | ||||
| 	/* Print */ | ||||
| 	/* Zoom */ | ||||
| 	/* PageLayoutZoom */ | ||||
| 	/* PageBreakZoom */ | ||||
| 	/* ShowPageBreakZoom */ | ||||
| 	/* DefaultRowHeight */ | ||||
| 	/* DefaultColumnWidth */ | ||||
| 	/* StandardWidth */ | ||||
| 
 | ||||
| 	if(wb && wb.Workbook && wb.Workbook.Sheets && wb.Workbook.Sheets[idx]) { | ||||
| 		/* Visible */ | ||||
| 		if(!!wb.Workbook.Sheets[idx].Hidden) o.push("<Visible>" + (wb.Workbook.Sheets[idx].Hidden == 1 ? "SheetHidden" : "SheetVeryHidden") + "</Visible>"); | ||||
| 		if(!!wb.Workbook.Sheets[idx].Hidden) o.push(writextag("Visible", (wb.Workbook.Sheets[idx].Hidden == 1 ? "SheetHidden" : "SheetVeryHidden"), {})); | ||||
| 		else { | ||||
| 			/* Selected */ | ||||
| 			for(var i = 0; i < idx; ++i) if(wb.Workbook.Sheets[i] && !wb.Workbook.Sheets[i].Hidden) break; | ||||
| 			if(i == idx) o.push("<Selected/>"); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* LeftColumnVisible */ | ||||
| 	/* DisplayRightToLeft */ | ||||
| 	/* GridlineColorIndex */ | ||||
| 	/* DisplayFormulas */ | ||||
| 	/* DoNotDisplayGridlines */ | ||||
| 	/* DoNotDisplayHeadings */ | ||||
| 	/* DoNotDisplayOutline */ | ||||
| 	/* ApplyAutomaticOutlineStyles */ | ||||
| 	/* NoSummaryRowsBelowDetail */ | ||||
| 	/* NoSummaryColumnsRightDetail */ | ||||
| 	/* DoNotDisplayZeros */ | ||||
| 	/* ActiveRow */ | ||||
| 	/* ActiveColumn */ | ||||
| 	/* FilterOn */ | ||||
| 	/* RangeSelection */ | ||||
| 	/* TopRowVisible */ | ||||
| 	/* TopRowBottomPane */ | ||||
| 	/* LeftColumnRightPane */ | ||||
| 	/* ActivePane */ | ||||
| 	/* SplitHorizontal */ | ||||
| 	/* SplitVertical */ | ||||
| 	/* FreezePanes */ | ||||
| 	/* FrozenNoSplit */ | ||||
| 	/* TabColorIndex */ | ||||
| 	/* Panes */ | ||||
| 
 | ||||
| 	/* NOTE: Password not supported in XLML Format */ | ||||
| 	if(ws['!protect']) { | ||||
| 		o.push(writetag("ProtectContents", "True")); | ||||
| 		if(ws['!protect'].objects) o.push(writetag("ProtectObjects", "True")); | ||||
| 		if(ws['!protect'].scenarios) o.push(writetag("ProtectScenarios", "True")); | ||||
| 		if(ws['!protect'].selectLockedCells != null && !ws['!protect'].selectLockedCells) o.push(writetag("EnableSelection", "NoSelection")); | ||||
| 		else if(ws['!protect'].selectUnlockedCells != null && !ws['!protect'].selectUnlockedCells) o.push(writetag("EnableSelection", "UnlockedCells")); | ||||
| 	[ | ||||
| 		[ "formatColumns", "AllowFormatCells" ], | ||||
| 		[ "formatRows", "AllowSizeCols" ], | ||||
| 		[ "formatCells", "AllowSizeRows" ], | ||||
| 		[ "insertColumns", "AllowInsertCols" ], | ||||
| 		[ "insertRows", "AllowInsertRows" ], | ||||
| 		[ "insertHyperlinks", "AllowInsertHyperlinks" ], | ||||
| 		[ "deleteColumns", "AllowDeleteCols" ], | ||||
| 		[ "deleteRows", "AllowDeleteRows" ], | ||||
| 		[ "sort", "AllowSort" ], | ||||
| 		[ "autoFilter", "AllowFilter" ], | ||||
| 		[ "pivotTables", "AllowUsePivotTables" ] | ||||
| 	].forEach(function(x) { if(ws['!protect'][x[0]]) o.push("<"+x[1]+"/>"); }); | ||||
| 	} | ||||
| 
 | ||||
| 	if(o.length == 0) return ""; | ||||
| 	return writextag("WorksheetOptions", o.join(""), {xmlns:XLMLNS.x}); | ||||
| } | ||||
| @ -12982,12 +13083,13 @@ function slurp(R, blob, length, opts) { | ||||
| 
 | ||||
| function safe_format_xf(p, opts, date1904) { | ||||
| 	if(p.t === 'z') return; | ||||
| 	if(p.t === 'e') { p.w = p.w || BErr[p.v]; } | ||||
| 	if(!p.XF) return; | ||||
| 	try { | ||||
| 		var fmtid = p.XF.ifmt||0; | ||||
| 		if(opts.cellNF) p.z = SSF._table[fmtid]; | ||||
| 		if(p.t === 'e'){} | ||||
| 	} catch(e) { if(opts.WTF) throw e; } | ||||
| 	if(!opts || opts.cellText !== false) try { | ||||
| 		if(p.t === 'e') { p.w = p.w || BErr[p.v]; } | ||||
| 		else if(fmtid === 0) { | ||||
| 			if(p.t === 'n') { | ||||
| 				if((p.v|0) === p.v) p.w = SSF._general_int(p.v); | ||||
| @ -15370,7 +15472,7 @@ var parse_content_xml = (function() { | ||||
| 						isstub = textpidx == 0; | ||||
| 					} | ||||
| 					if(comments.length > 0) { q.c = comments; comments = []; } | ||||
| 					if(textp) q.w = textp; | ||||
| 					if(textp && opts.cellText !== false) q.w = textp; | ||||
| 					if(!isstub || opts.sheetStubs) { | ||||
| 						if(!(opts.sheetRows && opts.sheetRows < R)) { | ||||
| 							if(opts.dense) { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user