forked from sheetjs/sheetjs
		
	XLS/XLSX/XLSB Row Outline Levels (closes #723)
note: @sheetjsdev rewrote implementation, original PR author used
This commit is contained in:
		
							parent
							
								
									859691b87b
								
							
						
					
					
						commit
						d28cc872c7
					
				| @ -1204,9 +1204,14 @@ type RowInfo = { | ||||
| 	/* row height is specified in one of the following ways: */ | ||||
| 	hpx?:    number;  // height in screen pixels | ||||
| 	hpt?:    number;  // height in points | ||||
| 
 | ||||
| 	level?:  number;  // 0-indexed outline / group level | ||||
| }; | ||||
| ``` | ||||
| 
 | ||||
| Note: Excel UI displays the base outline level as `1` and the max level as `8`. | ||||
| The `level` field stores the base outline as `0` and the max level as `7`. | ||||
| 
 | ||||
| <details> | ||||
| 	<summary><b>Implementation details</b> (click to show)</summary> | ||||
| 
 | ||||
|  | ||||
| @ -224,6 +224,8 @@ function parse_Row(blob, length) { | ||||
| 	blob.l += 4; // reserved(2), unused(2)
 | ||||
| 	var flags = blob.read_shift(1); // various flags
 | ||||
| 	blob.l += 3; // reserved(8), ixfe(12), flags(4)
 | ||||
| 	if(flags & 0x07) z.level = flags & 0x07; | ||||
| 	// collapsed: flags & 0x10
 | ||||
| 	if(flags & 0x20) z.hidden = true; | ||||
| 	if(flags & 0x40) z.hpt = miyRw / 20; | ||||
| 	return z; | ||||
|  | ||||
| @ -262,6 +262,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) { | ||||
| 			rowobj = {}; rowrite = false; | ||||
| 			if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); } | ||||
| 			if(tag.hidden == "1") { rowrite = true; rowobj.hidden = true; } | ||||
| 			if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; } | ||||
| 			if(rowrite) rows[tagr-1] = rowobj; | ||||
| 		} | ||||
| 
 | ||||
| @ -391,7 +392,7 @@ function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook | ||||
| 			if(_cell === undefined) continue; | ||||
| 			if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb)) != null) r.push(cell); | ||||
| 		} | ||||
| 		if(r.length > 0) { | ||||
| 		if(r.length > 0 || rows && rows[R]) { | ||||
| 			var params = ({r:rr}/*:any*/); | ||||
| 			if(rows && rows[R]) { | ||||
| 				var row = rows[R]; | ||||
| @ -400,10 +401,24 @@ function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook | ||||
| 				if (row.hpx) height = px2pt(row.hpx); | ||||
| 				else if (row.hpt) height = row.hpt; | ||||
| 				if (height > -1) { params.ht = height; params.customHeight = 1; } | ||||
| 				if (row.level) { params.outlineLevel = row.level; } | ||||
| 			} | ||||
| 			o[o.length] = (writextag('row', r.join(""), params)); | ||||
| 		} | ||||
| 	} | ||||
| 	if(rows) for(; R < rows.length; ++R) { | ||||
| 		if(rows && rows[R]) { | ||||
| 			var params = ({r:R+1}/*:any*/); | ||||
| 			var row = rows[R]; | ||||
| 			if(row.hidden) params.hidden = 1; | ||||
| 			var height = -1; | ||||
| 			if (row.hpx) height = px2pt(row.hpx); | ||||
| 			else if (row.hpt) height = row.hpt; | ||||
| 			if (height > -1) { params.ht = height; params.customHeight = 1; } | ||||
| 			if (row.level) { params.outlineLevel = row.level; } | ||||
| 			o[o.length] = (writextag('row', "", params)); | ||||
| 		} | ||||
| 	} | ||||
| 	return o.join(""); | ||||
| } | ||||
| 
 | ||||
| @ -429,7 +444,11 @@ function write_ws_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ { | ||||
| 	o[o.length] = write_ws_xml_sheetviews(ws, opts, idx, wb); | ||||
| 
 | ||||
| 	/* TODO: store in WB, process styles */ | ||||
| 	if(opts.sheetFormat) o[o.length] = (writextag('sheetFormatPr', null, {defaultRowHeight:opts.sheetFormat.defaultRowHeight||'16', baseColWidth:opts.sheetFormat.baseColWidth||'10' })); | ||||
| 	if(opts.sheetFormat) o[o.length] = (writextag('sheetFormatPr', null, { | ||||
| 		defaultRowHeight:opts.sheetFormat.defaultRowHeight||'16', | ||||
| 		baseColWidth:opts.sheetFormat.baseColWidth||'10', | ||||
| 		outlineLevelRow:opts.sheetFormat.outlineLevelRow||'7' | ||||
| 	})); | ||||
| 
 | ||||
| 	if(ws['!cols'] != null && ws['!cols'].length > 0) o[o.length] = (write_ws_xml_cols(ws, ws['!cols'])); | ||||
| 
 | ||||
|  | ||||
| @ -9,6 +9,7 @@ function parse_BrtRowHdr(data, length) { | ||||
| 	data.l += 1; // TODO: top/bot padding
 | ||||
| 	var flags = data.read_shift(1); | ||||
| 	data.l = tgt; | ||||
| 	if(flags & 0x07) z.level = flags & 0x07; | ||||
| 	if(flags & 0x10) z.hidden = true; | ||||
| 	if(flags & 0x20) z.hpt = miyRw / 20; | ||||
| 	return z; | ||||
| @ -28,6 +29,7 @@ function write_BrtRowHdr(R/*:number*/, range, ws) { | ||||
| 	o.write_shift(1, 0); /* top/bot padding */ | ||||
| 
 | ||||
| 	var flags = 0x0; | ||||
| 	if(row.level) flags |= row.level; | ||||
| 	if(row.hidden) flags |= 0x10; | ||||
| 	if(row.hpx || row.hpt) flags |= 0x20; | ||||
| 	o.write_shift(1, flags); | ||||
| @ -62,7 +64,7 @@ function write_BrtRowHdr(R/*:number*/, range, ws) { | ||||
| } | ||||
| function write_row_header(ba, ws, range, R) { | ||||
| 	var o = write_BrtRowHdr(R, range, ws); | ||||
| 	if(o.length > 17) write_record(ba, 'BrtRowHdr', o); | ||||
| 	if(o.length > 17 || (ws['!rows']||[])[R]) write_record(ba, 'BrtRowHdr', o); | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.812 BrtWsDim */ | ||||
| @ -426,7 +428,7 @@ function parse_ws_bin(data, _opts, rels, wb, themes, styles)/*:Worksheet*/ { | ||||
| 				if(opts.sheetRows && opts.sheetRows <= row.r) end=true; | ||||
| 				rr = encode_row(R = row.r); | ||||
| 				opts['!row'] = row.r; | ||||
| 				if(val.hidden || val.hpt) { | ||||
| 				if(val.hidden || val.hpt || val.level != null) { | ||||
| 					if(val.hpt) val.hpx = pt2px(val.hpt); | ||||
| 					rowinfo[val.r] = val; | ||||
| 				} | ||||
| @ -684,12 +686,14 @@ function write_CELLTABLE(ba, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbo | ||||
| 	var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols = []; | ||||
| 	write_record(ba, 'BrtBeginSheetData'); | ||||
| 	var dense = Array.isArray(ws); | ||||
| 	for(var R = range.s.r; R <= range.e.r; ++R) { | ||||
| 	var cap = range.e.r; | ||||
| 	if(ws['!rows']) cap = Math.max(range.e.r, ws['!rows'].length - 1); | ||||
| 	for(var R = range.s.r; R <= cap; ++R) { | ||||
| 		rr = encode_row(R); | ||||
| 		/* [ACCELLTABLE] */ | ||||
| 		/* BrtRowHdr */ | ||||
| 		write_row_header(ba, ws, range, R); | ||||
| 		for(var C = range.s.c; C <= range.e.c; ++C) { | ||||
| 		if(R <= range.e.r) for(var C = range.s.c; C <= range.e.c; ++C) { | ||||
| 			/* *16384CELL */ | ||||
| 			if(R === range.s.r) cols[C] = encode_col(C); | ||||
| 			ref = cols[C] + rr; | ||||
|  | ||||
| @ -521,6 +521,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 				} break; | ||||
| 				case 'Row': { | ||||
| 					var rowobj = {}; | ||||
| 					if(val.level != null) { rowinfo[val.r] = rowobj; rowobj.level = val.level; } | ||||
| 					if(val.hidden) { rowinfo[val.r] = rowobj; rowobj.hidden = true; } | ||||
| 					if(val.hpt) { | ||||
| 						rowinfo[val.r] = rowobj; | ||||
|  | ||||
| @ -289,6 +289,9 @@ var parse_content_xml = (function() { | ||||
| 
 | ||||
| 			case 'forms': break; // 12.25.2 13.2
 | ||||
| 			case 'table-column': break; // 9.1.6 <table:table-column>
 | ||||
| 			/* TODO: outline levels */ | ||||
| 			case 'table-row-group': break; // 9.1.9 <table:table-row-group>
 | ||||
| 			case 'table-column-group': break; // 9.1.10 <table:table-column-group>
 | ||||
| 
 | ||||
| 			case 'null-date': break; // 9.4.2 <table:null-date> TODO: date1904
 | ||||
| 
 | ||||
|  | ||||
| @ -75,9 +75,14 @@ type RowInfo = { | ||||
| 	/* row height is specified in one of the following ways: */ | ||||
| 	hpx?:    number;  // height in screen pixels | ||||
| 	hpt?:    number;  // height in points | ||||
| 
 | ||||
| 	level?:  number;  // 0-indexed outline / group level | ||||
| }; | ||||
| ``` | ||||
| 
 | ||||
| Note: Excel UI displays the base outline level as `1` and the max level as `8`. | ||||
| The `level` field stores the base outline as `0` and the max level as `7`. | ||||
| 
 | ||||
| <details> | ||||
| 	<summary><b>Implementation details</b> (click to show)</summary> | ||||
| 
 | ||||
|  | ||||
| @ -1105,9 +1105,14 @@ type RowInfo = { | ||||
| 	/* row height is specified in one of the following ways: */ | ||||
| 	hpx?:    number;  // height in screen pixels | ||||
| 	hpt?:    number;  // height in points | ||||
| 
 | ||||
| 	level?:  number;  // 0-indexed outline / group level | ||||
| }; | ||||
| ``` | ||||
| 
 | ||||
| Note: Excel UI displays the base outline level as `1` and the max level as `8`. | ||||
| The `level` field stores the base outline as `0` and the max level as `7`. | ||||
| 
 | ||||
| 
 | ||||
| Excel internally stores row heights in points.  The default resolution is 72 DPI | ||||
| or 96 PPI, so the pixel and point size should agree.  For different resolutions | ||||
|  | ||||
							
								
								
									
										33
									
								
								test.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										33
									
								
								test.js
									
									
									
									
									
								
							| @ -97,6 +97,12 @@ var paths = { | ||||
| 	nfxlsx:  dir + 'number_format.xlsm', | ||||
| 	nfxlsb:  dir + 'number_format.xlsb', | ||||
| 
 | ||||
| 	olxls:  dir + 'outline.xls', | ||||
| 	olxls5:  dir + 'outline.biff5', | ||||
| 	olxlsx:  dir + 'outline.xlsx', | ||||
| 	olxlsb:  dir + 'outline.xlsb', | ||||
| 	olods:  dir + 'outline.ods', | ||||
| 
 | ||||
| 	pmxls:  dir + 'page_margins_2016.xls', | ||||
| 	pmxls5: dir + 'page_margins_2016_5.xls', | ||||
| 	pmxml:  dir + 'page_margins_2016.xml', | ||||
| @ -901,6 +907,7 @@ describe('parse features', function() { | ||||
| 
 | ||||
| 	describe('row properties', function() { | ||||
| 		var wb1, wb2, wb3, wb4, wb5, wb6; | ||||
| 		var ol1, ol2, ol3, ol4, ol5; | ||||
| 		var bef = (function() { | ||||
| 			X = require(modp); | ||||
| 			wb1 = X.readFile(paths.rhxlsx, {cellStyles:true}); | ||||
| @ -909,6 +916,11 @@ describe('parse features', function() { | ||||
| 			wb4 = X.readFile(paths.rhxls5, {cellStyles:true}); | ||||
| 			wb5 = X.readFile(paths.rhxml, {cellStyles:true}); | ||||
| 			wb6 = X.readFile(paths.rhslk, {cellStyles:true}); | ||||
| 			ol1 = X.readFile(paths.olxlsx, {cellStyles:true}); | ||||
| 			ol2 = X.readFile(paths.olxlsb, {cellStyles:true}); | ||||
| 			ol3 = X.readFile(paths.olxls, {cellStyles:true}); | ||||
| 			ol4 = X.readFile(paths.olxls5, {cellStyles:true}); | ||||
| 			ol5 = X.readFile(paths.olods, {cellStyles:true}); | ||||
| 		}); | ||||
| 		if(typeof before != 'undefined') before(bef); | ||||
| 		else it('before', bef); | ||||
| @ -930,6 +942,22 @@ describe('parse features', function() { | ||||
| 				assert.equal(x[3].hpx, 100); | ||||
| 			}); | ||||
| 		}); | ||||
| 		it('should have correct outline levels', function() { | ||||
| 			/* TODO: ODS */ | ||||
| 			[ol1, ol2, ol3, ol4/*, ol5*/].map(function(x) { return x.Sheets.Sheet1; }).forEach(function(ws) { | ||||
| 				var rows = ws['!rows']; | ||||
| 				for(var i = 0; i < 29; ++i) { | ||||
| 					var cell = get_cell(ws, "A" + X.utils.encode_row(i)); | ||||
| 					var lvl = (rows[i]||{}).level||0; | ||||
| 					if(!cell || cell.t == 's') assert.equal(lvl, 0); | ||||
| 					else if(cell.t == 'n') { | ||||
| 						if(cell.v == 0) assert.equal(lvl, 0); | ||||
| 						else assert.equal(lvl, cell.v); | ||||
| 					} | ||||
| 				} | ||||
| 				assert.equal(rows[29].level, 7); | ||||
| 			}); | ||||
| 		}); | ||||
| 	}); | ||||
| 
 | ||||
| 	describe('merge cells',function() { | ||||
| @ -1400,18 +1428,21 @@ describe('roundtrip features', function() { | ||||
| 		}); }); | ||||
| 	}); | ||||
| 
 | ||||
| 	/* TODO: ODS and BIFF5/8 */ | ||||
| 	describe('should preserve row properties', function() { [ | ||||
| 			'xlml', /*'biff2', */ 'xlsx', 'xlsb', 'slk' | ||||
| 		].forEach(function(w) { it(w, function() { | ||||
| 				var ws1 = X.utils.aoa_to_sheet([["hpx12"],["hpt24"],["hpx48"],["hidden"]]); | ||||
| 				ws1['!rows'] = [{hpx:12},{hpt:24},{hpx:48},{hidden:true}]; | ||||
| 				for(var i = 0; i <= 7; ++i) ws1['!rows'].push({level:i}); | ||||
| 				var wb1 = {SheetNames:["Sheet1"], Sheets:{Sheet1:ws1}}; | ||||
| 				var wb2 = X.read(X.write(wb1, {bookType:w, type:"buffer"}), {type:"buffer", cellStyles:true}); | ||||
| 				var wb2 = X.read(X.write(wb1, {bookType:w, type:"buffer", cellStyles:true}), {type:"buffer", cellStyles:true}); | ||||
| 				var ws2 = wb2.Sheets.Sheet1; | ||||
| 				assert.equal(ws2['!rows'][0].hpx, 12); | ||||
| 				assert.equal(ws2['!rows'][1].hpt, 24); | ||||
| 				assert.equal(ws2['!rows'][2].hpx, 48); | ||||
| 				assert.equal(ws2['!rows'][3].hidden, true); | ||||
| 				if(w == 'xlsb' || w == 'xlsx') for(i = 0; i <= 7; ++i) assert.equal((ws2['!rows'][4+i]||{}).level||0, i); | ||||
| 		}); }); | ||||
| 	}); | ||||
| 
 | ||||
|  | ||||
| @ -1 +1 @@ | ||||
| Subproject commit 249b005fddf7cea0b2c2d1aff5a2414e47e70c0e | ||||
| Subproject commit d0f58a9e4b0519a513a1e44d1b28109fd4a8e13e | ||||
| @ -25,7 +25,7 @@ var wsrows = [ | ||||
| 	{hpt: 12}, // "points"
 | ||||
| 	{hpx: 16}, // "pixels"
 | ||||
| 	, | ||||
| 	{hpx: 24}, | ||||
| 	{hpx: 24, level:3}, | ||||
| 	{hidden: true}, // hide row
 | ||||
| 	{hidden: false} | ||||
| ]; | ||||
|  | ||||
							
								
								
									
										45
									
								
								xlsx.flow.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										45
									
								
								xlsx.flow.js
									
									
									
									
									
								
							| @ -4292,6 +4292,8 @@ function parse_Row(blob, length) { | ||||
| 	blob.l += 4; // reserved(2), unused(2)
 | ||||
| 	var flags = blob.read_shift(1); // various flags
 | ||||
| 	blob.l += 3; // reserved(8), ixfe(12), flags(4)
 | ||||
| 	if(flags & 0x07) z.level = flags & 0x07; | ||||
| 	// collapsed: flags & 0x10
 | ||||
| 	if(flags & 0x20) z.hidden = true; | ||||
| 	if(flags & 0x40) z.hpt = miyRw / 20; | ||||
| 	return z; | ||||
| @ -5730,7 +5732,8 @@ var PRN = (function() { | ||||
| 		function finish_cell() { | ||||
| 			var s = str.slice(start, end); | ||||
| 			var cell = ({}/*:any*/); | ||||
| 			if(s.charCodeAt(0) == 0x3D) { cell.t = 'n'; cell.f = s.substr(1); } | ||||
| 			if(o.raw) { cell.t = 's'; cell.v = s; } | ||||
| 			else if(s.charCodeAt(0) == 0x3D) { cell.t = 'n'; cell.f = s.substr(1); } | ||||
| 			else if(s == "TRUE") { cell.t = 'b'; cell.v = true; } | ||||
| 			else if(s == "FALSE") { cell.t = 'b'; cell.v = false; } | ||||
| 			else if(!isNaN(v = +s)) { cell.t = 'n'; cell.w = s; cell.v = v; } | ||||
| @ -5824,7 +5827,6 @@ function read_wb_ID(d, opts) { | ||||
| 		return PRN.to_workbook(d, opts); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| var WK_ = (function() { | ||||
| 	function lotushopper(data, cb/*:RecordHopperCB*/, opts/*:any*/) { | ||||
| 		if(!data) return; | ||||
| @ -10999,6 +11001,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) { | ||||
| 			rowobj = {}; rowrite = false; | ||||
| 			if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); } | ||||
| 			if(tag.hidden == "1") { rowrite = true; rowobj.hidden = true; } | ||||
| 			if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; } | ||||
| 			if(rowrite) rows[tagr-1] = rowobj; | ||||
| 		} | ||||
| 
 | ||||
| @ -11128,7 +11131,7 @@ function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook | ||||
| 			if(_cell === undefined) continue; | ||||
| 			if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb)) != null) r.push(cell); | ||||
| 		} | ||||
| 		if(r.length > 0) { | ||||
| 		if(r.length > 0 || rows && rows[R]) { | ||||
| 			var params = ({r:rr}/*:any*/); | ||||
| 			if(rows && rows[R]) { | ||||
| 				var row = rows[R]; | ||||
| @ -11137,10 +11140,24 @@ function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook | ||||
| 				if (row.hpx) height = px2pt(row.hpx); | ||||
| 				else if (row.hpt) height = row.hpt; | ||||
| 				if (height > -1) { params.ht = height; params.customHeight = 1; } | ||||
| 				if (row.level) { params.outlineLevel = row.level; } | ||||
| 			} | ||||
| 			o[o.length] = (writextag('row', r.join(""), params)); | ||||
| 		} | ||||
| 	} | ||||
| 	if(rows) for(; R < rows.length; ++R) { | ||||
| 		if(rows && rows[R]) { | ||||
| 			var params = ({r:R+1}/*:any*/); | ||||
| 			var row = rows[R]; | ||||
| 			if(row.hidden) params.hidden = 1; | ||||
| 			var height = -1; | ||||
| 			if (row.hpx) height = px2pt(row.hpx); | ||||
| 			else if (row.hpt) height = row.hpt; | ||||
| 			if (height > -1) { params.ht = height; params.customHeight = 1; } | ||||
| 			if (row.level) { params.outlineLevel = row.level; } | ||||
| 			o[o.length] = (writextag('row', "", params)); | ||||
| 		} | ||||
| 	} | ||||
| 	return o.join(""); | ||||
| } | ||||
| 
 | ||||
| @ -11166,7 +11183,11 @@ function write_ws_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ { | ||||
| 	o[o.length] = write_ws_xml_sheetviews(ws, opts, idx, wb); | ||||
| 
 | ||||
| 	/* TODO: store in WB, process styles */ | ||||
| 	if(opts.sheetFormat) o[o.length] = (writextag('sheetFormatPr', null, {defaultRowHeight:opts.sheetFormat.defaultRowHeight||'16', baseColWidth:opts.sheetFormat.baseColWidth||'10' })); | ||||
| 	if(opts.sheetFormat) o[o.length] = (writextag('sheetFormatPr', null, { | ||||
| 		defaultRowHeight:opts.sheetFormat.defaultRowHeight||'16', | ||||
| 		baseColWidth:opts.sheetFormat.baseColWidth||'10', | ||||
| 		outlineLevelRow:opts.sheetFormat.outlineLevelRow||'7' | ||||
| 	})); | ||||
| 
 | ||||
| 	if(ws['!cols'] != null && ws['!cols'].length > 0) o[o.length] = (write_ws_xml_cols(ws, ws['!cols'])); | ||||
| 
 | ||||
| @ -11260,6 +11281,7 @@ function parse_BrtRowHdr(data, length) { | ||||
| 	data.l += 1; // TODO: top/bot padding
 | ||||
| 	var flags = data.read_shift(1); | ||||
| 	data.l = tgt; | ||||
| 	if(flags & 0x07) z.level = flags & 0x07; | ||||
| 	if(flags & 0x10) z.hidden = true; | ||||
| 	if(flags & 0x20) z.hpt = miyRw / 20; | ||||
| 	return z; | ||||
| @ -11279,6 +11301,7 @@ function write_BrtRowHdr(R/*:number*/, range, ws) { | ||||
| 	o.write_shift(1, 0); /* top/bot padding */ | ||||
| 
 | ||||
| 	var flags = 0x0; | ||||
| 	if(row.level) flags |= row.level; | ||||
| 	if(row.hidden) flags |= 0x10; | ||||
| 	if(row.hpx || row.hpt) flags |= 0x20; | ||||
| 	o.write_shift(1, flags); | ||||
| @ -11313,7 +11336,7 @@ function write_BrtRowHdr(R/*:number*/, range, ws) { | ||||
| } | ||||
| function write_row_header(ba, ws, range, R) { | ||||
| 	var o = write_BrtRowHdr(R, range, ws); | ||||
| 	if(o.length > 17) write_record(ba, 'BrtRowHdr', o); | ||||
| 	if(o.length > 17 || (ws['!rows']||[])[R]) write_record(ba, 'BrtRowHdr', o); | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.812 BrtWsDim */ | ||||
| @ -11677,7 +11700,7 @@ function parse_ws_bin(data, _opts, rels, wb, themes, styles)/*:Worksheet*/ { | ||||
| 				if(opts.sheetRows && opts.sheetRows <= row.r) end=true; | ||||
| 				rr = encode_row(R = row.r); | ||||
| 				opts['!row'] = row.r; | ||||
| 				if(val.hidden || val.hpt) { | ||||
| 				if(val.hidden || val.hpt || val.level != null) { | ||||
| 					if(val.hpt) val.hpx = pt2px(val.hpt); | ||||
| 					rowinfo[val.r] = val; | ||||
| 				} | ||||
| @ -11935,12 +11958,14 @@ function write_CELLTABLE(ba, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbo | ||||
| 	var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols = []; | ||||
| 	write_record(ba, 'BrtBeginSheetData'); | ||||
| 	var dense = Array.isArray(ws); | ||||
| 	for(var R = range.s.r; R <= range.e.r; ++R) { | ||||
| 	var cap = range.e.r; | ||||
| 	if(ws['!rows']) cap = Math.max(range.e.r, ws['!rows'].length - 1); | ||||
| 	for(var R = range.s.r; R <= cap; ++R) { | ||||
| 		rr = encode_row(R); | ||||
| 		/* [ACCELLTABLE] */ | ||||
| 		/* BrtRowHdr */ | ||||
| 		write_row_header(ba, ws, range, R); | ||||
| 		for(var C = range.s.c; C <= range.e.c; ++C) { | ||||
| 		if(R <= range.e.r) for(var C = range.s.c; C <= range.e.c; ++C) { | ||||
| 			/* *16384CELL */ | ||||
| 			if(R === range.s.r) cols[C] = encode_col(C); | ||||
| 			ref = cols[C] + rr; | ||||
| @ -14524,6 +14549,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 				} break; | ||||
| 				case 'Row': { | ||||
| 					var rowobj = {}; | ||||
| 					if(val.level != null) { rowinfo[val.r] = rowobj; rowobj.level = val.level; } | ||||
| 					if(val.hidden) { rowinfo[val.r] = rowobj; rowobj.hidden = true; } | ||||
| 					if(val.hpt) { | ||||
| 						rowinfo[val.r] = rowobj; | ||||
| @ -16644,6 +16670,9 @@ var parse_content_xml = (function() { | ||||
| 
 | ||||
| 			case 'forms': break; // 12.25.2 13.2
 | ||||
| 			case 'table-column': break; // 9.1.6 <table:table-column>
 | ||||
| 			/* TODO: outline levels */ | ||||
| 			case 'table-row-group': break; // 9.1.9 <table:table-row-group>
 | ||||
| 			case 'table-column-group': break; // 9.1.10 <table:table-column-group>
 | ||||
| 
 | ||||
| 			case 'null-date': break; // 9.4.2 <table:null-date> TODO: date1904
 | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										45
									
								
								xlsx.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										45
									
								
								xlsx.js
									
									
									
									
									
								
							| @ -4230,6 +4230,8 @@ function parse_Row(blob, length) { | ||||
| 	blob.l += 4; // reserved(2), unused(2)
 | ||||
| 	var flags = blob.read_shift(1); // various flags
 | ||||
| 	blob.l += 3; // reserved(8), ixfe(12), flags(4)
 | ||||
| 	if(flags & 0x07) z.level = flags & 0x07; | ||||
| 	// collapsed: flags & 0x10
 | ||||
| 	if(flags & 0x20) z.hidden = true; | ||||
| 	if(flags & 0x40) z.hpt = miyRw / 20; | ||||
| 	return z; | ||||
| @ -5668,7 +5670,8 @@ var PRN = (function() { | ||||
| 		function finish_cell() { | ||||
| 			var s = str.slice(start, end); | ||||
| 			var cell = ({}); | ||||
| 			if(s.charCodeAt(0) == 0x3D) { cell.t = 'n'; cell.f = s.substr(1); } | ||||
| 			if(o.raw) { cell.t = 's'; cell.v = s; } | ||||
| 			else if(s.charCodeAt(0) == 0x3D) { cell.t = 'n'; cell.f = s.substr(1); } | ||||
| 			else if(s == "TRUE") { cell.t = 'b'; cell.v = true; } | ||||
| 			else if(s == "FALSE") { cell.t = 'b'; cell.v = false; } | ||||
| 			else if(!isNaN(v = +s)) { cell.t = 'n'; cell.w = s; cell.v = v; } | ||||
| @ -5762,7 +5765,6 @@ function read_wb_ID(d, opts) { | ||||
| 		return PRN.to_workbook(d, opts); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| var WK_ = (function() { | ||||
| 	function lotushopper(data, cb, opts) { | ||||
| 		if(!data) return; | ||||
| @ -10933,6 +10935,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) { | ||||
| 			rowobj = {}; rowrite = false; | ||||
| 			if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); } | ||||
| 			if(tag.hidden == "1") { rowrite = true; rowobj.hidden = true; } | ||||
| 			if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; } | ||||
| 			if(rowrite) rows[tagr-1] = rowobj; | ||||
| 		} | ||||
| 
 | ||||
| @ -11062,7 +11065,7 @@ function write_ws_xml_data(ws, opts, idx, wb, rels) { | ||||
| 			if(_cell === undefined) continue; | ||||
| 			if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb)) != null) r.push(cell); | ||||
| 		} | ||||
| 		if(r.length > 0) { | ||||
| 		if(r.length > 0 || rows && rows[R]) { | ||||
| 			var params = ({r:rr}); | ||||
| 			if(rows && rows[R]) { | ||||
| 				var row = rows[R]; | ||||
| @ -11071,10 +11074,24 @@ function write_ws_xml_data(ws, opts, idx, wb, rels) { | ||||
| 				if (row.hpx) height = px2pt(row.hpx); | ||||
| 				else if (row.hpt) height = row.hpt; | ||||
| 				if (height > -1) { params.ht = height; params.customHeight = 1; } | ||||
| 				if (row.level) { params.outlineLevel = row.level; } | ||||
| 			} | ||||
| 			o[o.length] = (writextag('row', r.join(""), params)); | ||||
| 		} | ||||
| 	} | ||||
| 	if(rows) for(; R < rows.length; ++R) { | ||||
| 		if(rows && rows[R]) { | ||||
| 			var params = ({r:R+1}); | ||||
| 			var row = rows[R]; | ||||
| 			if(row.hidden) params.hidden = 1; | ||||
| 			var height = -1; | ||||
| 			if (row.hpx) height = px2pt(row.hpx); | ||||
| 			else if (row.hpt) height = row.hpt; | ||||
| 			if (height > -1) { params.ht = height; params.customHeight = 1; } | ||||
| 			if (row.level) { params.outlineLevel = row.level; } | ||||
| 			o[o.length] = (writextag('row', "", params)); | ||||
| 		} | ||||
| 	} | ||||
| 	return o.join(""); | ||||
| } | ||||
| 
 | ||||
| @ -11100,7 +11117,11 @@ function write_ws_xml(idx, opts, wb, rels) { | ||||
| 	o[o.length] = write_ws_xml_sheetviews(ws, opts, idx, wb); | ||||
| 
 | ||||
| 	/* TODO: store in WB, process styles */ | ||||
| 	if(opts.sheetFormat) o[o.length] = (writextag('sheetFormatPr', null, {defaultRowHeight:opts.sheetFormat.defaultRowHeight||'16', baseColWidth:opts.sheetFormat.baseColWidth||'10' })); | ||||
| 	if(opts.sheetFormat) o[o.length] = (writextag('sheetFormatPr', null, { | ||||
| 		defaultRowHeight:opts.sheetFormat.defaultRowHeight||'16', | ||||
| 		baseColWidth:opts.sheetFormat.baseColWidth||'10', | ||||
| 		outlineLevelRow:opts.sheetFormat.outlineLevelRow||'7' | ||||
| 	})); | ||||
| 
 | ||||
| 	if(ws['!cols'] != null && ws['!cols'].length > 0) o[o.length] = (write_ws_xml_cols(ws, ws['!cols'])); | ||||
| 
 | ||||
| @ -11194,6 +11215,7 @@ function parse_BrtRowHdr(data, length) { | ||||
| 	data.l += 1; // TODO: top/bot padding
 | ||||
| 	var flags = data.read_shift(1); | ||||
| 	data.l = tgt; | ||||
| 	if(flags & 0x07) z.level = flags & 0x07; | ||||
| 	if(flags & 0x10) z.hidden = true; | ||||
| 	if(flags & 0x20) z.hpt = miyRw / 20; | ||||
| 	return z; | ||||
| @ -11213,6 +11235,7 @@ function write_BrtRowHdr(R, range, ws) { | ||||
| 	o.write_shift(1, 0); /* top/bot padding */ | ||||
| 
 | ||||
| 	var flags = 0x0; | ||||
| 	if(row.level) flags |= row.level; | ||||
| 	if(row.hidden) flags |= 0x10; | ||||
| 	if(row.hpx || row.hpt) flags |= 0x20; | ||||
| 	o.write_shift(1, flags); | ||||
| @ -11247,7 +11270,7 @@ function write_BrtRowHdr(R, range, ws) { | ||||
| } | ||||
| function write_row_header(ba, ws, range, R) { | ||||
| 	var o = write_BrtRowHdr(R, range, ws); | ||||
| 	if(o.length > 17) write_record(ba, 'BrtRowHdr', o); | ||||
| 	if(o.length > 17 || (ws['!rows']||[])[R]) write_record(ba, 'BrtRowHdr', o); | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.812 BrtWsDim */ | ||||
| @ -11610,7 +11633,7 @@ function parse_ws_bin(data, _opts, rels, wb, themes, styles) { | ||||
| 				if(opts.sheetRows && opts.sheetRows <= row.r) end=true; | ||||
| 				rr = encode_row(R = row.r); | ||||
| 				opts['!row'] = row.r; | ||||
| 				if(val.hidden || val.hpt) { | ||||
| 				if(val.hidden || val.hpt || val.level != null) { | ||||
| 					if(val.hpt) val.hpx = pt2px(val.hpt); | ||||
| 					rowinfo[val.r] = val; | ||||
| 				} | ||||
| @ -11868,12 +11891,14 @@ function write_CELLTABLE(ba, ws, idx, opts, wb) { | ||||
| 	var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols = []; | ||||
| 	write_record(ba, 'BrtBeginSheetData'); | ||||
| 	var dense = Array.isArray(ws); | ||||
| 	for(var R = range.s.r; R <= range.e.r; ++R) { | ||||
| 	var cap = range.e.r; | ||||
| 	if(ws['!rows']) cap = Math.max(range.e.r, ws['!rows'].length - 1); | ||||
| 	for(var R = range.s.r; R <= cap; ++R) { | ||||
| 		rr = encode_row(R); | ||||
| 		/* [ACCELLTABLE] */ | ||||
| 		/* BrtRowHdr */ | ||||
| 		write_row_header(ba, ws, range, R); | ||||
| 		for(var C = range.s.c; C <= range.e.c; ++C) { | ||||
| 		if(R <= range.e.r) for(var C = range.s.c; C <= range.e.c; ++C) { | ||||
| 			/* *16384CELL */ | ||||
| 			if(R === range.s.r) cols[C] = encode_col(C); | ||||
| 			ref = cols[C] + rr; | ||||
| @ -14450,6 +14475,7 @@ wb.opts.Date1904 = Workbook.WBProps.date1904 = val; break; | ||||
| 				} break; | ||||
| 				case 'Row': { | ||||
| 					var rowobj = {}; | ||||
| 					if(val.level != null) { rowinfo[val.r] = rowobj; rowobj.level = val.level; } | ||||
| 					if(val.hidden) { rowinfo[val.r] = rowobj; rowobj.hidden = true; } | ||||
| 					if(val.hpt) { | ||||
| 						rowinfo[val.r] = rowobj; | ||||
| @ -16570,6 +16596,9 @@ var parse_content_xml = (function() { | ||||
| 
 | ||||
| 			case 'forms': break; // 12.25.2 13.2
 | ||||
| 			case 'table-column': break; // 9.1.6 <table:table-column>
 | ||||
| 			/* TODO: outline levels */ | ||||
| 			case 'table-row-group': break; // 9.1.9 <table:table-row-group>
 | ||||
| 			case 'table-column-group': break; // 9.1.10 <table:table-column-group>
 | ||||
| 
 | ||||
| 			case 'null-date': break; // 9.4.2 <table:null-date> TODO: date1904
 | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user