forked from sheetjs/sheetjs
		
	version bump 0.11.17: sheet_add_{aoa,json}
- Skip extraneous trailing records (fixes #938 h/t @benjaminleetmaa) - XLS -> XLML oddities (fixes #678 h/t @buserror) - ionic demo - sheet_add_aoa and sheet_add_json Issues: - fixes #947 h/t @fpasxos - fixes #666 h/t @samuelkavin - fixes #301 h/t @acgentry - fixes #561 h/t @Ideandro
This commit is contained in:
		
							parent
							
								
									a7d3779724
								
							
						
					
					
						commit
						1d74977718
					
				
							
								
								
									
										143
									
								
								README.md
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										143
									
								
								README.md
									
									
									
									
									
								
							| @ -190,7 +190,7 @@ The [`demos` directory](demos/) includes sample projects for: | ||||
| 
 | ||||
| **Frameworks and APIs** | ||||
| - [`angular 1.x`](demos/angular/) | ||||
| - [`angular 2.x / 4.x / 5.x`](demos/angular2/) | ||||
| - [`angular 2 / 4 / 5 and ionic`](demos/angular2/) | ||||
| - [`meteor`](demos/meteor/) | ||||
| - [`react and react-native`](demos/react/) | ||||
| - [`vue 2.x and weex`](demos/vue/) | ||||
| @ -721,6 +721,8 @@ Utilities are available in the `XLSX.utils` object and are described in the | ||||
| - `aoa_to_sheet` converts an array of arrays of JS data to a worksheet. | ||||
| - `json_to_sheet` converts an array of JS objects to a worksheet. | ||||
| - `table_to_sheet` converts a DOM TABLE element to a worksheet. | ||||
| - `sheet_add_aoa` adds an array of arrays of JS data to an existing worksheet. | ||||
| - `sheet_add_json` adds an array of JS objects to an existing worksheet. | ||||
| 
 | ||||
| 
 | ||||
| **Exporting:** | ||||
| @ -1742,6 +1744,61 @@ var ws = XLSX.utils.aoa_to_sheet([ | ||||
| ``` | ||||
| </details> | ||||
| 
 | ||||
| `XLSX.utils.sheet_add_aoa` takes an array of arrays of JS values and updates an | ||||
| existing worksheet object.  It follows the same process as `aoa_to_sheet` and | ||||
| accepts an options argument: | ||||
| 
 | ||||
| | Option Name |  Default | Description                                         | | ||||
| | :---------- | :------: | :-------------------------------------------------- | | ||||
| |`dateNF`     |  FMT 14  | Use specified date format in string output          | | ||||
| |`cellDates`  |  false   | Store dates as type `d` (default is `n`)            | | ||||
| |`sheetStubs` |  false   | Create cell objects of type `z` for `null` values   | | ||||
| |`origin`     |          | Use specified cell as starting point (see below)    | | ||||
| 
 | ||||
| `origin` is expected to be one of: | ||||
| 
 | ||||
| | `origin`         | Description                                               | | ||||
| | :--------------- | :-------------------------------------------------------- | | ||||
| | (cell object)    | Use specified cell (cell object)                          | | ||||
| | (string)         | Use specified cell (A1-style cell)                        | | ||||
| | (number >= 0)    | Start from the first column at specified row (0-indexed)  | | ||||
| | -1               | Append to bottom of worksheet starting on first column    | | ||||
| | (default)        | Start from cell A1                                        | | ||||
| 
 | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>Examples</b> (click to show)</summary> | ||||
| 
 | ||||
| Consider the worksheet: | ||||
| 
 | ||||
| ``` | ||||
| XXX| A | B | C | D | E | F | G | | ||||
| ---+---+---+---+---+---+---+---+ | ||||
|  1 | S | h | e | e | t | J | S | | ||||
|  2 | 1 | 2 |   |   | 5 | 6 | 7 | | ||||
|  3 | 2 | 3 |   |   | 6 | 7 | 8 | | ||||
|  4 | 3 | 4 |   |   | 7 | 8 | 9 | | ||||
|  5 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | | ||||
| ``` | ||||
| 
 | ||||
| This worksheet can be built up in the order `A1:G1, A2:B4, E2:G4, A5:G5`: | ||||
| 
 | ||||
| ```js | ||||
| /* Initial row */ | ||||
| var ws = XLSX.utils.aoa_to_sheet([ "SheetJS".split("") ]); | ||||
| 
 | ||||
| /* Write data starting at A2 */ | ||||
| XLSX.utils.sheet_add_aoa(ws, [[1,2], [2,3], [3,4]], {origin: "A2"}); | ||||
| 
 | ||||
| /* Write data starting at E2 */ | ||||
| XLSX.utils.sheet_add_aoa(ws, [[5,6,7], [6,7,8], [7,8,9]], {origin:{r:1, c:4}}); | ||||
| 
 | ||||
| /* Append row */ | ||||
| XLSX.utils.sheet_add_aoa(ws, [[4,5,6,7,8,9,0]], {origin: -1}); | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| ### Array of Objects Input | ||||
| 
 | ||||
| `XLSX.utils.json_to_sheet` takes an array of objects and returns a worksheet | ||||
| @ -1754,19 +1811,95 @@ default column order is determined by the first appearance of the field using | ||||
| |`header`     |          | Use specified column order (default `Object.keys`)  | | ||||
| |`dateNF`     |  FMT 14  | Use specified date format in string output          | | ||||
| |`cellDates`  |  false   | Store dates as type `d` (default is `n`)            | | ||||
| |`skipHeader` |  false   | If true, do not include header row in output        | | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>Examples</b> (click to show)</summary> | ||||
| 
 | ||||
| The original sheet cannot be reproduced because JS object keys must be unique. | ||||
| After replacing the second `e` and `S` with `e_1` and `S_1`: | ||||
| The original sheet cannot be reproduced in the obvious way since JS object keys | ||||
| must be unique. After replacing the second `e` and `S` with `e_1` and `S_1`: | ||||
| 
 | ||||
| ```js | ||||
| var ws = XLSX.utils.json_to_sheet([ | ||||
|   {S:1,h:2,e:3,e_1:4,t:5,J:6,S_1:7}, | ||||
|   {S:2,h:3,e:4,e_1:5,t:6,J:7,S_1:8} | ||||
|   { S:1, h:2, e:3, e_1:4, t:5, J:6, S_1:7 }, | ||||
|   { S:2, h:3, e:4, e_1:5, t:6, J:7, S_1:8 } | ||||
| ], {header:["S","h","e","e_1","t","J","S_1"]}); | ||||
| ``` | ||||
| 
 | ||||
| Alternatively, the header row can be skipped: | ||||
| 
 | ||||
| ```js | ||||
| var ws = XLSX.utils.json_to_sheet([ | ||||
|   { A:"S", B:"h", C:"e", D:"e", E:"t", F:"J", G:"S" }, | ||||
|   { A: 1,  B: 2,  C: 3,  D: 4,  E: 5,  F: 6,  G: 7  }, | ||||
|   { A: 2,  B: 3,  C: 4,  D: 5,  E: 6,  F: 7,  G: 8  } | ||||
| ], {header:["A","B","C","D","E","F","G"], skipHeader:true}); | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| `XLSX.utils.sheet_add_json` takes an array of objects and updates an existing | ||||
| worksheet object.  It follows the same process as `json_to_sheet` and accepts | ||||
| an options argument: | ||||
| 
 | ||||
| | Option Name |  Default | Description                                         | | ||||
| | :---------- | :------: | :-------------------------------------------------- | | ||||
| |`header`     |          | Use specified column order (default `Object.keys`)  | | ||||
| |`dateNF`     |  FMT 14  | Use specified date format in string output          | | ||||
| |`cellDates`  |  false   | Store dates as type `d` (default is `n`)            | | ||||
| |`skipHeader` |  false   | If true, do not include header row in output        | | ||||
| |`origin`     |          | Use specified cell as starting point (see below)    | | ||||
| 
 | ||||
| `origin` is expected to be one of: | ||||
| 
 | ||||
| | `origin`         | Description                                               | | ||||
| | :--------------- | :-------------------------------------------------------- | | ||||
| | (cell object)    | Use specified cell (cell object)                          | | ||||
| | (string)         | Use specified cell (A1-style cell)                        | | ||||
| | (number >= 0)    | Start from the first column at specified row (0-indexed)  | | ||||
| | -1               | Append to bottom of worksheet starting on first column    | | ||||
| | (default)        | Start from cell A1                                        | | ||||
| 
 | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>Examples</b> (click to show)</summary> | ||||
| 
 | ||||
| Consider the worksheet: | ||||
| 
 | ||||
| ``` | ||||
| XXX| A | B | C | D | E | F | G | | ||||
| ---+---+---+---+---+---+---+---+ | ||||
|  1 | S | h | e | e | t | J | S | | ||||
|  2 | 1 | 2 |   |   | 5 | 6 | 7 | | ||||
|  3 | 2 | 3 |   |   | 6 | 7 | 8 | | ||||
|  4 | 3 | 4 |   |   | 7 | 8 | 9 | | ||||
|  5 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | | ||||
| ``` | ||||
| 
 | ||||
| This worksheet can be built up in the order `A1:G1, A2:B4, E2:G4, A5:G5`: | ||||
| 
 | ||||
| ```js | ||||
| /* Initial row */ | ||||
| var ws = XLSX.utils.json_to_sheet([ | ||||
|   { A: "S", B: "h", C: "e", D: "e", E: "t", F: "J", G: "S" } | ||||
| ], {header: ["A", "B", "C", "D", "E", "F", "G"], skipHeader: true}); | ||||
| 
 | ||||
| /* Write data starting at A2 */ | ||||
| XLSX.utils.sheet_add_json(ws, [ | ||||
|   { A: 1, B: 2 }, { A: 2, B: 3 }, { A: 3, B: 4 } | ||||
| ], {skipHeader: true, origin: "A2"}); | ||||
| 
 | ||||
| /* Write data starting at E2 */ | ||||
| XLSX.utils.sheet_add_json(ws, [ | ||||
|   { A: 5, B: 6, C: 7 }, { A: 6, B: 7, C: 8 }, { A: 7, B: 8, C: 9 } | ||||
| ], {skipHeader: true, origin: { r: 1, c: 4 }, header: [ "A", "B", "C" ]}); | ||||
| 
 | ||||
| /* Append row */ | ||||
| XLSX.utils.sheet_add_json(ws, [ | ||||
|   { A: 4, B: 5, C: 6, D: 7, E: 8, F: 9, G: 0 } | ||||
| ], {header: ["A", "B", "C", "D", "E", "F", "G"], skipHeader: true, origin: -1}); | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| ### HTML Table Input | ||||
|  | ||||
| @ -1 +1 @@ | ||||
| XLSX.version = '0.11.16'; | ||||
| XLSX.version = '0.11.17'; | ||||
|  | ||||
| @ -62,11 +62,16 @@ function escapexml(text/*:string*/, xml/*:?boolean*/)/*:string*/{ | ||||
| function escapexmltag(text/*:string*/)/*:string*/{ return escapexml(text).replace(/ /g,"_x0020_"); } | ||||
| 
 | ||||
| var htmlcharegex = /[\u0000-\u001f]/g; | ||||
| function escapehtml(text){ | ||||
| function escapehtml(text/*:string*/)/*:string*/{ | ||||
| 	var s = text + ''; | ||||
| 	return s.replace(decregex, function(y) { return rencoding[y]; }).replace(htmlcharegex,function(s) { return "&#x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + ";"; }); | ||||
| } | ||||
| 
 | ||||
| function escapexlml(text/*:string*/)/*:string*/{ | ||||
| 	var s = text + ''; | ||||
| 	return s.replace(decregex, function(y) { return rencoding[y]; }).replace(htmlcharegex,function(s) { return "&#x" + (s.charCodeAt(0).toString(16)).toUpperCase() + ";"; }); | ||||
| } | ||||
| 
 | ||||
| /* TODO: handle codepages */ | ||||
| var xlml_fixstr/*:StringConv*/ = (function() { | ||||
| 	var entregex = /&#(\d+);/g; | ||||
|  | ||||
| @ -5,8 +5,8 @@ function shift_cell_xls(cell/*:CellAddress*/, tgt/*:any*/, opts/*:?any*/)/*:Cell | ||||
| 		if(out.cRel) out.c += tgt.s.c; | ||||
| 		if(out.rRel) out.r += tgt.s.r; | ||||
| 	} else { | ||||
| 		out.c += tgt.c; | ||||
| 		out.r += tgt.r; | ||||
| 		if(out.cRel) out.c += tgt.c; | ||||
| 		if(out.rRel) out.r += tgt.r; | ||||
| 	} | ||||
| 	if(!opts || opts.biff < 12) { | ||||
| 		while(out.c >= 0x100) out.c -= 0x100; | ||||
|  | ||||
| @ -80,20 +80,38 @@ function sheet_to_workbook(sheet/*:Worksheet*/, opts)/*:Workbook*/ { | ||||
| 	return { SheetNames: [n], Sheets: sheets }; | ||||
| } | ||||
| 
 | ||||
| function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ { | ||||
| function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ { | ||||
| 	var o = opts || {}; | ||||
| 	if(DENSE != null && o.dense == null) o.dense = DENSE; | ||||
| 	var ws/*:Worksheet*/ = o.dense ? ([]/*:any*/) : ({}/*:any*/); | ||||
| 	var dense = _ws ? Array.isArray(_ws) : o.dense; | ||||
| 	if(DENSE != null && dense == null) dense = DENSE; | ||||
| 	var ws/*:Worksheet*/ = _ws || (dense ? ([]/*:any*/) : ({}/*:any*/)); | ||||
| 	var _R = 0, _C = 0; | ||||
| 	if(ws && o.origin != null) { | ||||
| 		if(typeof o.origin == 'number') _R = o.origin; | ||||
| 		else { | ||||
| 			var _origin/*:CellAddress*/ = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin; | ||||
| 			_R = _origin.r; _C = _origin.c; | ||||
| 		} | ||||
| 	} | ||||
| 	var range/*:Range*/ = ({s: {c:10000000, r:10000000}, e: {c:0, r:0}}/*:any*/); | ||||
| 	if(ws['!ref']) { | ||||
| 		var _range = safe_decode_range(ws['!ref']); | ||||
| 		range.s.c = _range.s.c; | ||||
| 		range.s.r = _range.s.r; | ||||
| 		range.e.c = Math.max(range.e.c, _range.e.c); | ||||
| 		range.e.r = Math.max(range.e.r, _range.e.r); | ||||
| 		if(_R == -1) range.e.r = _R = _range.e.r + 1; | ||||
| 	} | ||||
| 	for(var R = 0; R != data.length; ++R) { | ||||
| 		for(var C = 0; C != data[R].length; ++C) { | ||||
| 			if(typeof data[R][C] === 'undefined') continue; | ||||
| 			var cell/*:Cell*/ = ({v: data[R][C] }/*:any*/); | ||||
| 			if(Array.isArray(cell.v)) { cell.f = data[R][C][1]; cell.v = cell.v[0]; } | ||||
| 			if(range.s.r > R) range.s.r = R; | ||||
| 			if(range.s.c > C) range.s.c = C; | ||||
| 			if(range.e.r < R) range.e.r = R; | ||||
| 			if(range.e.c < C) range.e.c = C; | ||||
| 			var __R = _R + R, __C = _C + C; | ||||
| 			if(range.s.r > __R) range.s.r = __R; | ||||
| 			if(range.s.c > __C) range.s.c = __C; | ||||
| 			if(range.e.r < __R) range.e.r = __R; | ||||
| 			if(range.e.c < __C) range.e.c = __C; | ||||
| 			if(cell.v === null) { if(cell.f) cell.t = 'n'; else if(!o.cellStubs) continue; else cell.t = 'z'; } | ||||
| 			else if(typeof cell.v === 'number') cell.t = 'n'; | ||||
| 			else if(typeof cell.v === 'boolean') cell.t = 'b'; | ||||
| @ -103,11 +121,11 @@ function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ { | ||||
| 				else { cell.t = 'n'; cell.v = datenum(cell.v); cell.w = SSF.format(cell.z, cell.v); } | ||||
| 			} | ||||
| 			else cell.t = 's'; | ||||
| 			if(o.dense) { | ||||
| 				if(!ws[R]) ws[R] = []; | ||||
| 				ws[R][C] = cell; | ||||
| 			if(dense) { | ||||
| 				if(!ws[__R]) ws[__R] = []; | ||||
| 				ws[__R][__C] = cell; | ||||
| 			} else { | ||||
| 				var cell_ref = encode_cell(({c:C,r:R}/*:any*/)); | ||||
| 				var cell_ref = encode_cell(({c:__C,r:__R}/*:any*/)); | ||||
| 				ws[cell_ref] = cell; | ||||
| 			} | ||||
| 		} | ||||
| @ -115,4 +133,5 @@ function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ { | ||||
| 	if(range.s.c < 10000000) ws['!ref'] = encode_range(range); | ||||
| 	return ws; | ||||
| } | ||||
| function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ { return sheet_add_aoa(null, data, opts); } | ||||
| 
 | ||||
|  | ||||
| @ -78,6 +78,7 @@ function xlml_write_custprops(Props, Custprops, opts) { | ||||
| 	if(Custprops) keys(Custprops).forEach(function(k) { | ||||
| 		/*:: if(!Custprops) return; */ | ||||
| 		if(!Custprops.hasOwnProperty(k)) return; | ||||
| 		if(Props && Props.hasOwnProperty(k)) return; | ||||
| 		var m = Custprops[k]; | ||||
| 		var t = "string"; | ||||
| 		if(typeof m == 'number') { t = "float"; m = String(m); } | ||||
|  | ||||
| @ -673,7 +673,7 @@ function parse_ShrFmla(blob, length, opts) { | ||||
| 	blob.l++; | ||||
| 	var cUse = blob.read_shift(1); | ||||
| 	length -= 8; | ||||
| 	return [parse_SharedParsedFormula(blob, length, opts), cUse]; | ||||
| 	return [parse_SharedParsedFormula(blob, length, opts), cUse, ref]; | ||||
| } | ||||
| 
 | ||||
| /* 2.4.4 TODO */ | ||||
|  | ||||
| @ -62,10 +62,8 @@ function parse_DataSpaceDefinition(blob, length)/*:Array<string>*/ { | ||||
| function parse_TransformInfoHeader(blob, length) { | ||||
| 	var o = {}; | ||||
| 	var len = blob.read_shift(4); | ||||
| 	var tgt = blob.l + len - 4; | ||||
| 	blob.l += 4; // must be 0x1
 | ||||
| 	o.id = blob.read_shift(0, 'lpp4'); | ||||
| 	if(tgt != blob.l) throw new Error("Bad TransformInfoHeader record: " + blob.l + " != " + tgt); | ||||
| 	o.name = blob.read_shift(0, 'lpp4'); | ||||
| 	o.R = parse_CRYPTOVersion(blob, 4); | ||||
| 	o.U = parse_CRYPTOVersion(blob, 4); | ||||
|  | ||||
| @ -18,12 +18,13 @@ var rc_to_a1 = (function(){ | ||||
| 
 | ||||
| var crefregex = /(^|[^._A-Z0-9])([$]?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])([$]?)([1-9]\d{0,5}|10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6])(?![_.\(A-Za-z0-9])/g; | ||||
| var a1_to_rc =(function(){ | ||||
| 	return function a1_to_rc(fstr, base) { | ||||
| 	return function a1_to_rc(fstr/*:string*/, base/*:CellAddress*/) { | ||||
| 		return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5, off, str) { | ||||
| 			/* TODO: handle fixcol / fixrow */ | ||||
| 			var c = decode_col($3) - base.c; | ||||
| 			var r = decode_row($5) - base.r; | ||||
| 			return $1 + "R" + (r == 0 ? "" : "[" + r + "]") + "C" + (c == 0 ? "" : "[" + c + "]"); | ||||
| 			var c = decode_col($3) - ($2 ? 0 : base.c); | ||||
| 			var r = decode_row($5) - ($4 ? 0 : base.r); | ||||
| 			var R = (r == 0 ? "" : !$4 ? "[" + r + "]" : (r+1)); | ||||
| 			var C = (c == 0 ? "" : !$2 ? "[" + c + "]" : (c+1)); | ||||
| 			return $1 + "R" + R + "C" + C; | ||||
| 		}); | ||||
| 	}; | ||||
| })(); | ||||
|  | ||||
| @ -67,7 +67,7 @@ function parse_RgceLocRel(blob, length, opts) { | ||||
| 	if(biff >= 2 && biff <= 5) return parse_RgceLocRel_BIFF2(blob, length, opts); | ||||
| 	var r = blob.read_shift(biff >= 12 ? 4 : 2); | ||||
| 	var cl = blob.read_shift(2); | ||||
| 	var cRel = (cl & 0x8000) >> 15, rRel = (cl & 0x4000) >> 14; | ||||
| 	var cRel = (cl & 0x4000) >> 14, rRel = (cl & 0x8000) >> 15; | ||||
| 	cl &= 0x3FFF; | ||||
| 	if(rRel == 1) while(r > 0x7FFFF) r -= 0x100000; | ||||
| 	if(cRel == 1) while(cl > 0x1FFF) cl = cl - 0x4000; | ||||
| @ -840,7 +840,7 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks, | ||||
| 			case 'PtgErr': /* 2.5.198.57 */ | ||||
| 				stack.push(/*::String(*/f[1]/*::)*/); break; | ||||
| 			case 'PtgAreaN': /* 2.5.198.31 TODO */ | ||||
| 				type = f[1][0]; r = shift_range_xls(f[1][1], _range, opts); | ||||
| 				type = f[1][0]; r = shift_range_xls(f[1][1], cell ? {s:cell} : _range, opts); | ||||
| 				stack.push(encode_range_xls((r/*:any*/), opts)); | ||||
| 				break; | ||||
| 			case 'PtgArea': /* 2.5.198.27 TODO: fixed points */ | ||||
|  | ||||
| @ -334,7 +334,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ { | ||||
| 			var _NamedRange = parsexmltag(Rn[0]); | ||||
| 			var _DefinedName/*:DefinedName*/ = ({ | ||||
| 				Name: _NamedRange.Name, | ||||
| 				Ref: rc_to_a1(_NamedRange.RefersTo.substr(1)) | ||||
| 				Ref: rc_to_a1(_NamedRange.RefersTo.substr(1), {r:0, c:0}) | ||||
| 			}/*:any*/); | ||||
| 			if(Workbook.Sheets.length>0) _DefinedName.Sheet=Workbook.Sheets.length-1; | ||||
| 			/*:: if(Workbook.Names) */Workbook.Names.push(_DefinedName); | ||||
| @ -864,6 +864,37 @@ function write_sty_xlml(wb, opts)/*:string*/ { | ||||
| 	}); | ||||
| 	return writextag("Styles", styles.join("")); | ||||
| } | ||||
| function write_name_xlml(n) { return writextag("NamedRange", null, {"ss:Name": n.Name, "ss:RefersTo":"=" + a1_to_rc(n.Ref, {r:0,c:0})}); } | ||||
| function write_names_xlml(wb, opts)/*:string*/ { | ||||
| 	if(!((wb||{}).Workbook||{}).Names) return ""; | ||||
| 	/*:: if(!wb || !wb.Workbook || !wb.Workbook.Names) throw new Error("unreachable"); */ | ||||
| 	var names/*:Array<any>*/ = wb.Workbook.Names; | ||||
| 	var out/*:Array<string>*/ = []; | ||||
| 	for(var i = 0; i < names.length; ++i) { | ||||
| 		var n = names[i]; | ||||
| 		if(n.Sheet != null) continue; | ||||
| 		if(n.Name.match(/^_xlfn\./)) continue; | ||||
| 		out.push(write_name_xlml(n)); | ||||
| 	} | ||||
| 	return writextag("Names", out.join("")); | ||||
| } | ||||
| function write_ws_xlml_names(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/)/*:string*/ { | ||||
| 	if(!ws) return ""; | ||||
| 	if(!((wb||{}).Workbook||{}).Names) return ""; | ||||
| 	/*:: if(!wb || !wb.Workbook || !wb.Workbook.Names) throw new Error("unreachable"); */ | ||||
| 	var names/*:Array<any>*/ = wb.Workbook.Names; | ||||
| 	var out/*:Array<string>*/ = []; | ||||
| 	outer: for(var i = 0; i < names.length; ++i) { | ||||
| 		var n = names[i]; | ||||
| 		if(n.Sheet != idx) continue; | ||||
| 		/*switch(n.Name) { | ||||
| 			case "_": continue; | ||||
| 		}*/ | ||||
| 		if(n.Name.match(/^_xlfn\./)) continue; | ||||
| 		out.push(write_name_xlml(n)); | ||||
| 	} | ||||
| 	return out.join(""); | ||||
| } | ||||
| /* WorksheetOptions */ | ||||
| function write_ws_xlml_wsopts(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/)/*:string*/ { | ||||
| 	if(!ws) return ""; | ||||
| @ -982,7 +1013,7 @@ function write_ws_xlml_comment(comments/*:Array<any>*/)/*:string*/ { | ||||
| 	}).join(""); | ||||
| } | ||||
| function write_ws_xlml_cell(cell, ref/*:string*/, ws, opts, idx/*:number*/, wb, addr)/*:string*/{ | ||||
| 	if(!cell || cell.v == undefined && cell.f == undefined) return "<Cell></Cell>"; | ||||
| 	if(!cell || cell.v == undefined && cell.f == undefined) return ""; | ||||
| 
 | ||||
| 	var attr = {}; | ||||
| 	if(cell.f) attr["ss:Formula"] = "=" + escapexml(a1_to_rc(cell.f, addr)); | ||||
| @ -1012,11 +1043,12 @@ function write_ws_xlml_cell(cell, ref/*:string*/, ws, opts, idx/*:number*/, wb, | ||||
| 		case 'b': t = 'Boolean'; p = (cell.v ? "1" : "0"); break; | ||||
| 		case 'e': t = 'Error'; p = BErr[cell.v]; break; | ||||
| 		case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); if(cell.z == null) cell.z = cell.z || SSF._table[14]; break; | ||||
| 		case 's': t = 'String'; p = escapexml(cell.v||""); break; | ||||
| 		case 's': t = 'String'; p = escapexlml(cell.v||""); break; | ||||
| 	} | ||||
| 	/* TODO: cell style */ | ||||
| 	var os = get_cell_style(opts.cellXfs, cell, opts); | ||||
| 	attr["ss:StyleID"] = "s" + (21+os); | ||||
| 	attr["ss:Index"] = addr.c + 1; | ||||
| 	var _v = (cell.v != null ? p : ""); | ||||
| 	var m = '<Data ss:Type="' + t + '">' + _v + '</Data>'; | ||||
| 
 | ||||
| @ -1076,8 +1108,11 @@ function write_ws_xlml(idx/*:number*/, opts, wb/*:Workbook*/)/*:string*/ { | ||||
| 	var s = wb.SheetNames[idx]; | ||||
| 	var ws = wb.Sheets[s]; | ||||
| 
 | ||||
| 	var t/*:string*/ = ws ? write_ws_xlml_names(ws, opts, idx, wb) : ""; | ||||
| 	if(t.length > 0) o.push("<Names>" + t + "</Names>"); | ||||
| 
 | ||||
| 	/* Table */ | ||||
| 	var t = ws ? write_ws_xlml_table(ws, opts, idx, wb) : ""; | ||||
| 	t = ws ? write_ws_xlml_table(ws, opts, idx, wb) : ""; | ||||
| 	if(t.length > 0) o.push("<Table>" + t + "</Table>"); | ||||
| 
 | ||||
| 	/* WorksheetOptions */ | ||||
| @ -1100,9 +1135,11 @@ function write_xlml(wb, opts)/*:string*/ { | ||||
| 	d.push(write_props_xlml(wb, opts)); | ||||
| 	d.push(write_wb_xlml(wb, opts)); | ||||
| 	d.push(""); | ||||
| 	d.push(""); | ||||
| 	for(var i = 0; i < wb.SheetNames.length; ++i) | ||||
| 		d.push(writextag("Worksheet", write_ws_xlml(i, opts, wb), {"ss:Name":escapexml(wb.SheetNames[i])})); | ||||
| 	d[2] = write_sty_xlml(wb, opts); | ||||
| 	d[3] = write_names_xlml(wb, opts); | ||||
| 	return XML_HEADER + writextag("Workbook", d.join(""), { | ||||
| 		'xmlns':      XLMLNS.ss, | ||||
| 		'xmlns:o':    XLMLNS.o, | ||||
|  | ||||
| @ -105,7 +105,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 	var cur_sheet = ""; | ||||
| 	var Preamble = {}; | ||||
| 	var lastcell, last_cell = "", cc, cmnt, rngC, rngR; | ||||
| 	var shared_formulae = {}; | ||||
| 	var sharedf = {}; | ||||
| 	var arrayf/*:Array<[Range, string]>*/ = []; | ||||
| 	var temp_val/*:Cell*/; | ||||
| 	var country; | ||||
| @ -144,13 +144,10 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 		} | ||||
| 		if(options.cellFormula && line.f) { | ||||
| 			for(var afi = 0; afi < arrayf.length; ++afi) { | ||||
| 				if(arrayf[afi][0].s.c > cell.c) continue; | ||||
| 				if(arrayf[afi][0].s.r > cell.r) continue; | ||||
| 				if(arrayf[afi][0].e.c < cell.c) continue; | ||||
| 				if(arrayf[afi][0].e.r < cell.r) continue; | ||||
| 				if(arrayf[afi][0].s.c > cell.c || arrayf[afi][0].s.r > cell.r) continue; | ||||
| 				if(arrayf[afi][0].e.c < cell.c || arrayf[afi][0].e.r < cell.r) continue; | ||||
| 				line.F = encode_range(arrayf[afi][0]); | ||||
| 				if(arrayf[afi][0].s.c != cell.c) delete line.f; | ||||
| 				if(arrayf[afi][0].s.r != cell.r) delete line.f; | ||||
| 				if(arrayf[afi][0].s.c != cell.c || arrayf[afi][0].s.r != cell.r) delete line.f; | ||||
| 				if(line.f) line.f = "" + stringify_formula(arrayf[afi][1], range, cell, supbooks, opts); | ||||
| 				break; | ||||
| 			} | ||||
| @ -167,7 +164,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 		enc: false, // encrypted
 | ||||
| 		sbcch: 0, // cch in the preceding SupBook
 | ||||
| 		snames: [], // sheetnames
 | ||||
| 		sharedf: shared_formulae, // shared formulae by address
 | ||||
| 		sharedf: sharedf, // shared formulae by address
 | ||||
| 		arrayf: arrayf, // array formulae array
 | ||||
| 		rrtabid: [], // RRTabId
 | ||||
| 		lastuser: "", // Last User from WriteAccess
 | ||||
| @ -223,6 +220,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 			if(R.n === 'EOF') val = R.f(blob, length, opts); | ||||
| 			else val = slurp(R, blob, length, opts); | ||||
| 			var Rn = R.n; | ||||
| 			if(file_depth == 0 && Rn != 'BOF') continue; | ||||
| 			/* nested switch statements to workaround V8 128 limit */ | ||||
| 			switch(Rn) { | ||||
| 				/* Workbook Options */ | ||||
| @ -253,16 +251,17 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 				case 'RRTabId': opts.rrtabid = val; break; | ||||
| 				case 'WinProtect': opts.winlocked = val; break; | ||||
| 				case 'Template': break; // TODO
 | ||||
| 				case 'RefreshAll': wb.opts.RefreshAll = val; break; | ||||
| 				case 'BookBool': break; // TODO
 | ||||
| 				case 'UsesELFs': break; | ||||
| 				case 'MTRSettings': break; | ||||
| 				case 'CalcCount': wb.opts.CalcCount = val; break; | ||||
| 				case 'CalcDelta': wb.opts.CalcDelta = val; break; | ||||
| 				case 'CalcIter': wb.opts.CalcIter = val; break; | ||||
| 				case 'CalcMode': wb.opts.CalcMode = val; break; | ||||
| 				case 'CalcPrecision': wb.opts.CalcPrecision = val; break; | ||||
| 				case 'CalcSaveRecalc': wb.opts.CalcSaveRecalc = val; break; | ||||
| 				case 'RefreshAll': | ||||
| 				case 'CalcCount': | ||||
| 				case 'CalcDelta': | ||||
| 				case 'CalcIter': | ||||
| 				case 'CalcMode': | ||||
| 				case 'CalcPrecision': | ||||
| 				case 'CalcSaveRecalc': | ||||
| 					wb.opts[Rn] = val; break; | ||||
| 				case 'CalcRefMode': opts.CalcRefMode = val; break; // TODO: implement R1C1
 | ||||
| 				case 'Uncalced': break; | ||||
| 				case 'ForceFullCalculation': wb.opts.FullCalc = val; break; | ||||
| @ -404,7 +403,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 						if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') { | ||||
| 							var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1]; | ||||
| 							var _fe = encode_cell({r:_fr, c:_fc}); | ||||
| 							if(shared_formulae[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); | ||||
| 							if(sharedf[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); | ||||
| 							else temp_val.F = ((options.dense ? (out[_fr]||[])[_fc]: out[_fe]) || {}).F; | ||||
| 						} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); | ||||
| 					} | ||||
| @ -444,7 +443,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 					if(last_cell) { | ||||
| 						/* TODO: capture range */ | ||||
| 						if(!last_formula) break; /* technically unreachable */ | ||||
| 						shared_formulae[encode_cell(last_formula.cell)]= val[0]; | ||||
| 						sharedf[encode_cell(last_formula.cell)]= val[0]; | ||||
| 						cc = options.dense ? (out[last_formula.cell.r]||[])[last_formula.cell.c] : out[encode_cell(last_formula.cell)]; | ||||
| 						(cc||{}).f = ""+stringify_formula(val[0], range, lastcell, supbooks, opts); | ||||
| 					} | ||||
|  | ||||
| @ -168,14 +168,29 @@ function sheet_to_formulae(sheet/*:Worksheet*/)/*:Array<string>*/ { | ||||
| 	return cmds; | ||||
| } | ||||
| 
 | ||||
| function json_to_sheet(js/*:Array<any>*/, opts)/*:Worksheet*/ { | ||||
| function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet*/ { | ||||
| 	var o = opts || {}; | ||||
| 	var ws = ({}/*:any*/); | ||||
| 	var offset = +!o.skipHeader; | ||||
| 	var ws/*:Worksheet*/ = _ws || ({}/*:any*/); | ||||
| 	var _R = 0, _C = 0; | ||||
| 	if(ws && o.origin != null) { | ||||
| 		if(typeof o.origin == 'number') _R = o.origin; | ||||
| 		else { | ||||
| 			var _origin/*:CellAddress*/ = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin; | ||||
| 			_R = _origin.r; _C = _origin.c; | ||||
| 		} | ||||
| 	} | ||||
| 	var cell/*:Cell*/; | ||||
| 	var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:0, r:js.length}}/*:any*/); | ||||
| 	var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:_C, r:_R + js.length - 1 + offset}}/*:any*/); | ||||
| 	if(ws['!ref']) { | ||||
| 		var _range = safe_decode_range(ws['!ref']); | ||||
| 		range.e.c = Math.max(range.e.c, _range.e.c); | ||||
| 		range.e.r = Math.max(range.e.r, _range.e.r); | ||||
| 		if(_R == -1) { _R = range.e.r + 1; range.e.r = _R + js.length - 1 + offset; } | ||||
| 	} | ||||
| 	var hdr/*:Array<string>*/ = o.header || [], C = 0; | ||||
| 
 | ||||
| 	js.forEach(function (JS, R) { | ||||
| 	js.forEach(function (JS, R/*:number*/) { | ||||
| 		keys(JS).filter(function(x) { return JS.hasOwnProperty(x); }).forEach(function(k) { | ||||
| 			if((C=hdr.indexOf(k)) == -1) hdr[C=hdr.length] = k; | ||||
| 			var v = JS[k]; | ||||
| @ -189,15 +204,17 @@ function json_to_sheet(js/*:Array<any>*/, opts)/*:Worksheet*/ { | ||||
| 				if(!o.cellDates) { t = 'n'; v = datenum(v); } | ||||
| 				z = o.dateNF || SSF._table[14]; | ||||
| 			} | ||||
| 			ws[encode_cell({c:C,r:R+1})] = cell = ({t:t, v:v}/*:any*/); | ||||
| 			ws[encode_cell({c:_C + C,r:_R + R + offset})] = cell = ({t:t, v:v}/*:any*/); | ||||
| 			if(z) cell.z = z; | ||||
| 		}); | ||||
| 	}); | ||||
| 	range.e.c = hdr.length - 1; | ||||
| 	for(C = 0; C < hdr.length; ++C) ws[encode_col(C) + "1"] = {t:'s', v:hdr[C]}; | ||||
| 	range.e.c = Math.max(range.e.c, _C + hdr.length - 1); | ||||
| 	var __R = encode_row(_R); | ||||
| 	if(offset) for(C = 0; C < hdr.length; ++C) ws[encode_col(C + _C) + __R] = {t:'s', v:hdr[C]}; | ||||
| 	ws['!ref'] = encode_range(range); | ||||
| 	return ws; | ||||
| } | ||||
| function json_to_sheet(js/*:Array<any>*/, opts)/*:Worksheet*/ { return sheet_add_json(null, js, opts); } | ||||
| 
 | ||||
| var utils/*:any*/ = { | ||||
| 	encode_col: encode_col, | ||||
| @ -214,6 +231,8 @@ var utils/*:any*/ = { | ||||
| 	make_csv: sheet_to_csv, | ||||
| 	make_json: sheet_to_json, | ||||
| 	make_formulae: sheet_to_formulae, | ||||
| 	sheet_add_aoa: sheet_add_aoa, | ||||
| 	sheet_add_json: sheet_add_json, | ||||
| 	aoa_to_sheet: aoa_to_sheet, | ||||
| 	json_to_sheet: json_to_sheet, | ||||
| 	table_to_sheet: parse_dom_table, | ||||
|  | ||||
| @ -19,7 +19,7 @@ can be installed with Bash on Windows or with `cygwin`. | ||||
| 
 | ||||
| **Frameworks and APIs** | ||||
| - [`angular 1.x`](angular/) | ||||
| - [`angular 2.x / 4.x / 5.x`](angular2/) | ||||
| - [`angular 2 / 4 / 5 and ionic`](angular2/) | ||||
| - [`meteor`](meteor/) | ||||
| - [`react and react-native`](react/) | ||||
| - [`vue 2.x and weex`](vue/) | ||||
|  | ||||
							
								
								
									
										1
									
								
								demos/angular2/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										1
									
								
								demos/angular2/.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1 +1,2 @@ | ||||
| dist | ||||
| SheetJSIonic | ||||
|  | ||||
| @ -21,3 +21,11 @@ angular: | ||||
| 	if [ ! -e node_modules/xlsx ]; then cd node_modules; ln -s ../../../ xlsx; cd -; fi | ||||
| 	ng build | ||||
| 
 | ||||
| .PHONY: ionic | ||||
| ionic: | ||||
| 	bash ./ionic.sh | ||||
| 
 | ||||
| .PHONY: ios android browser | ||||
| ios android browser: ionic | ||||
| 	cd SheetJSIonic; ionic cordova emulate $@ </dev/null; cd - | ||||
| 
 | ||||
|  | ||||
| @ -10,6 +10,9 @@ This demo uses an array of arrays (type `Array<Array<any>>`) as the core state. | ||||
| The component template includes a file input element, a table that updates with | ||||
| the data, and a button to export the data. | ||||
| 
 | ||||
| Other scripts in this demo show: | ||||
| - `ionic` deployment for iOS, android, and browser | ||||
| 
 | ||||
| ## Array of Arrays | ||||
| 
 | ||||
| `Array<Array<any>>` neatly maps to a table with `ngFor`: | ||||
| @ -114,4 +117,39 @@ SystemJS.config({ | ||||
| }); | ||||
| ``` | ||||
| 
 | ||||
| ## Ionic | ||||
| 
 | ||||
| <img src="screen.png" width="400px"/> | ||||
| 
 | ||||
| Reproducing the full project is a little bit tricky.  The included `ionic.sh` | ||||
| script performs the necessary installation steps. | ||||
| 
 | ||||
| `Array<Array<any>>` neatly maps to a table with `ngFor`: | ||||
| 
 | ||||
| ```html | ||||
| <ion-grid> | ||||
|   <ion-row *ngFor="let row of data"> | ||||
|     <ion-col *ngFor="let val of row"> | ||||
|       {{val}} | ||||
|     </ion-col> | ||||
|   </ion-row> | ||||
| </ion-grid> | ||||
| ``` | ||||
| 
 | ||||
| 
 | ||||
| `@ionic-native/file` reads and writes files on devices. `readAsBinaryString` | ||||
| returns strings that can be parsed with the `binary` type, and `array` type can | ||||
| easily be converted to blobs that can be exported with `writeFile`: | ||||
| 
 | ||||
| ```typescript | ||||
| /* read a workbook */ | ||||
| const bstr: string = await this.file.readAsBinaryString(url, filename); | ||||
| const wb: XLSX.WorkBook = XLSX.read(bstr, {type: 'binary'}); | ||||
| 
 | ||||
| /* write a workbook */ | ||||
| const wbout: ArrayBuffer = XLSX.write(wb, { bookType: 'xlsx', type: 'array' }); | ||||
| let blob = new Blob([wbout], {type: 'application/octet-stream'}); | ||||
| this.file.writeFile(url, filename, blob, {replace: true}); | ||||
| ``` | ||||
| 
 | ||||
| [](https://github.com/SheetJS/js-xlsx) | ||||
|  | ||||
							
								
								
									
										17
									
								
								demos/angular2/ionic.sh
									
									
									
									
									
										Executable file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										17
									
								
								demos/angular2/ionic.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,17 @@ | ||||
| #!/bin/bash | ||||
| if [ ! -e SheetJSIonic ]; then | ||||
| 	ionic start SheetJSIonic blank --cordova --no-git --no-link </dev/null | ||||
| 	cd SheetJSIonic | ||||
| 	ionic cordova platform add browser </dev/null | ||||
| 	ionic cordova platform add ios </dev/null | ||||
| 	ionic cordova plugin add cordova-plugin-file </dev/null | ||||
| 	npm install --save @ionic-native/file file-saver | ||||
| 	npm install --save xlsx | ||||
| 
 | ||||
| 	cp src/app/app.module.ts{,.bak} | ||||
| 	cat src/app/app.module.ts.bak | awk 'BEGIN{p=0} !/import/ && !p { ++p; print "import { File } from '"'"'@ionic-native/file'"'"';"; } 1; /providers: \[/ {print "    File,"}' > src/app/app.module.ts | ||||
| 	cd - | ||||
| fi | ||||
| 
 | ||||
| cp ionic.ts SheetJSIonic/src/pages/home/home.ts | ||||
| rm -f SheetJSIonic/src/pages/home/home.html | ||||
							
								
								
									
										109
									
								
								demos/angular2/ionic.ts
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										109
									
								
								demos/angular2/ionic.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,109 @@ | ||||
| /* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */ | ||||
| /* vim: set ts=2: */ | ||||
| import { Component } from '@angular/core'; | ||||
| 
 | ||||
| import * as XLSX from 'xlsx'; | ||||
| 
 | ||||
| import { File } from '@ionic-native/file'; | ||||
| import { saveAs } from 'file-saver'; | ||||
| 
 | ||||
| type AOA = any[][]; | ||||
| 
 | ||||
| @Component({ | ||||
|   selector: 'page-home', | ||||
|   template: ` | ||||
| <ion-header><ion-navbar><ion-title>SheetJS Ionic Demo</ion-title></ion-navbar></ion-header> | ||||
| 
 | ||||
| <ion-content padding> | ||||
|   <ion-grid> | ||||
|     <ion-row *ngFor="let row of data"> | ||||
|       <ion-col *ngFor="let val of row"> | ||||
|         {{val}} | ||||
|       </ion-col> | ||||
|     </ion-row> | ||||
|   </ion-grid> | ||||
| </ion-content> | ||||
| 
 | ||||
| <ion-footer> | ||||
|   <input type="file" (change)="onFileChange($event)" multiple="false" /> | ||||
|   <button ion-button color="secondary" (click)="import()">Import Data</button> | ||||
|   <button ion-button color="secondary" (click)="export()">Export Data</button> | ||||
| </ion-footer> | ||||
| ` | ||||
| }) | ||||
| 
 | ||||
| export class HomePage { | ||||
|   data: any[][] = [[1,2,3],[4,5,6]]; | ||||
|   constructor(public file: File) {}; | ||||
| 
 | ||||
|   read(bstr: string) { | ||||
|     /* read workbook */ | ||||
|     const wb: XLSX.WorkBook = XLSX.read(bstr, {type: 'binary'}); | ||||
| 
 | ||||
|     /* grab first sheet */ | ||||
|     const wsname: string = wb.SheetNames[0]; | ||||
|     const ws: XLSX.WorkSheet = wb.Sheets[wsname]; | ||||
| 
 | ||||
|     /* save data */ | ||||
|     this.data = <AOA>(XLSX.utils.sheet_to_json(ws, {header: 1})); | ||||
|   }; | ||||
| 
 | ||||
|   write(): ArrayBuffer { | ||||
|     /* generate worksheet */ | ||||
|     const ws: XLSX.WorkSheet = XLSX.utils.aoa_to_sheet(this.data); | ||||
| 
 | ||||
|     /* generate workbook and add the worksheet */ | ||||
|     const wb: XLSX.WorkBook = XLSX.utils.book_new(); | ||||
|     XLSX.utils.book_append_sheet(wb, ws, 'SheetJS'); | ||||
| 
 | ||||
|     /* save to ArrayBuffer */ | ||||
|     const wbout: ArrayBuffer = XLSX.write(wb, { bookType: 'xlsx', type: 'array' }); | ||||
|     return wbout; | ||||
|   }; | ||||
| 
 | ||||
|   /* File Input element for browser */ | ||||
|   onFileChange(evt: any) { | ||||
|     /* wire up file reader */ | ||||
|     const target: DataTransfer = <DataTransfer>(evt.target); | ||||
|     if (target.files.length !== 1) throw new Error('Cannot use multiple files'); | ||||
|     const reader: FileReader = new FileReader(); | ||||
|     reader.onload = (e: any) => { | ||||
|       const bstr: string = e.target.result; | ||||
|       this.read(bstr); | ||||
|     }; | ||||
|     reader.readAsBinaryString(target.files[0]); | ||||
|   }; | ||||
| 
 | ||||
|   /* Import button for mobile */ | ||||
|   async import() { | ||||
|     try { | ||||
|       const target: string = this.file.documentsDirectory || this.file.externalDataDirectory || this.file.dataDirectory || ''; | ||||
|       const dentry = await this.file.resolveDirectoryUrl(target); | ||||
|       const url: string = dentry.nativeURL || ''; | ||||
|       alert(`Attempting to read SheetJSIonic.xlsx from ${url}`) | ||||
|       const bstr: string = await this.file.readAsBinaryString(url, "SheetJSIonic.xlsx"); | ||||
|       this.read(bstr); | ||||
|     } catch(e) { | ||||
|       const m: string = e.message; | ||||
|       alert(m.match(/It was determined/) ? "Use File Input control" : `Error: ${m}`); | ||||
|     } | ||||
|   }; | ||||
| 
 | ||||
|   /* Export button */ | ||||
|   async export() { | ||||
|     const wbout: ArrayBuffer = this.write(); | ||||
|     const filename: string = "SheetJSIonic.xlsx"; | ||||
|     const blob: Blob = new Blob([wbout], {type: 'application/octet-stream'}); | ||||
|     try { | ||||
|       const target: string = this.file.documentsDirectory || this.file.externalDataDirectory || this.file.dataDirectory || ''; | ||||
|       const dentry = await this.file.resolveDirectoryUrl(target); | ||||
|       const url: string = dentry.nativeURL || ''; | ||||
|       await this.file.writeFile(url, filename, blob, {replace: true}); | ||||
|       alert(`Wrote to SheetJSIonic.xlsx in ${url}`); | ||||
|     } catch(e) { | ||||
|       if(e.message.match(/It was determined/)) saveAs(blob, filename); | ||||
|       else alert(`Error: ${e.message}`); | ||||
|     } | ||||
|   }; | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										
											BIN
										
									
								
								demos/angular2/screen.png
									
									
									
									
									
										Normal file
									
								
							
							
								
									
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								demos/angular2/screen.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 94 KiB | 
| @ -6,7 +6,7 @@ import * as XLSX from 'xlsx'; | ||||
| 
 | ||||
| import { saveAs } from 'file-saver'; | ||||
| 
 | ||||
| type AOA = Array<Array<any>>; | ||||
| type AOA = any[][]; | ||||
| 
 | ||||
| @Component({ | ||||
| 	selector: 'sheetjs', | ||||
|  | ||||
							
								
								
									
										30
									
								
								dist/xlsx.core.min.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										30
									
								
								dist/xlsx.core.min.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2
									
								
								dist/xlsx.core.min.map
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										2
									
								
								dist/xlsx.core.min.map
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										30
									
								
								dist/xlsx.full.min.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										30
									
								
								dist/xlsx.full.min.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2
									
								
								dist/xlsx.full.min.map
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										2
									
								
								dist/xlsx.full.min.map
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										179
									
								
								dist/xlsx.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										179
									
								
								dist/xlsx.js
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -4,7 +4,7 @@ | ||||
| /*global global, exports, module, require:false, process:false, Buffer:false */ | ||||
| var XLSX = {}; | ||||
| (function make_xlsx(XLSX){ | ||||
| XLSX.version = '0.11.16'; | ||||
| XLSX.version = '0.11.17'; | ||||
| var current_codepage = 1200, current_ansi = 1252; | ||||
| /*global cptable:true */ | ||||
| if(typeof module !== "undefined" && typeof require !== 'undefined') { | ||||
| @ -2051,6 +2051,11 @@ function escapehtml(text){ | ||||
| 	return s.replace(decregex, function(y) { return rencoding[y]; }).replace(htmlcharegex,function(s) { return "&#x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + ";"; }); | ||||
| } | ||||
| 
 | ||||
| function escapexlml(text){ | ||||
| 	var s = text + ''; | ||||
| 	return s.replace(decregex, function(y) { return rencoding[y]; }).replace(htmlcharegex,function(s) { return "&#x" + (s.charCodeAt(0).toString(16)).toUpperCase() + ";"; }); | ||||
| } | ||||
| 
 | ||||
| /* TODO: handle codepages */ | ||||
| var xlml_fixstr = (function() { | ||||
| 	var entregex = /&#(\d+);/g; | ||||
| @ -2255,7 +2260,7 @@ function write_double_le(b, v, idx) { | ||||
| 	b[idx + 7] = (e >> 4) | bs; | ||||
| } | ||||
| 
 | ||||
| var __toBuffer = function(bufs) { var x = []; for(var i = 0; i < bufs[0].length; ++i) { x.push.apply(x, bufs[0][i]); } return x; }; | ||||
| var __toBuffer = function(bufs) { var x=[],w=10240; for(var i=0;i<bufs[0].length;++i) for(var j=0,L=bufs[0][i].length;j<L;j+=w) x.push.apply(x, bufs[0][i].slice(j,j+w)); return x; }; | ||||
| var ___toBuffer = __toBuffer; | ||||
| var __utf16le = function(b,s,e) { var ss=[]; for(var i=s; i<e; i+=2) ss.push(String.fromCharCode(__readUInt16LE(b,i))); return ss.join("").replace(chr0,''); }; | ||||
| var ___utf16le = __utf16le; | ||||
| @ -2538,8 +2543,8 @@ function shift_cell_xls(cell, tgt, opts) { | ||||
| 		if(out.cRel) out.c += tgt.s.c; | ||||
| 		if(out.rRel) out.r += tgt.s.r; | ||||
| 	} else { | ||||
| 		out.c += tgt.c; | ||||
| 		out.r += tgt.r; | ||||
| 		if(out.cRel) out.c += tgt.c; | ||||
| 		if(out.rRel) out.r += tgt.r; | ||||
| 	} | ||||
| 	if(!opts || opts.biff < 12) { | ||||
| 		while(out.c >= 0x100) out.c -= 0x100; | ||||
| @ -2689,20 +2694,38 @@ function sheet_to_workbook(sheet, opts) { | ||||
| 	return { SheetNames: [n], Sheets: sheets }; | ||||
| } | ||||
| 
 | ||||
| function aoa_to_sheet(data, opts) { | ||||
| function sheet_add_aoa(_ws, data, opts) { | ||||
| 	var o = opts || {}; | ||||
| 	if(DENSE != null && o.dense == null) o.dense = DENSE; | ||||
| 	var ws = o.dense ? ([]) : ({}); | ||||
| 	var dense = _ws ? Array.isArray(_ws) : o.dense; | ||||
| 	if(DENSE != null && dense == null) dense = DENSE; | ||||
| 	var ws = _ws || (dense ? ([]) : ({})); | ||||
| 	var _R = 0, _C = 0; | ||||
| 	if(ws && o.origin != null) { | ||||
| 		if(typeof o.origin == 'number') _R = o.origin; | ||||
| 		else { | ||||
| 			var _origin = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin; | ||||
| 			_R = _origin.r; _C = _origin.c; | ||||
| 		} | ||||
| 	} | ||||
| 	var range = ({s: {c:10000000, r:10000000}, e: {c:0, r:0}}); | ||||
| 	if(ws['!ref']) { | ||||
| 		var _range = safe_decode_range(ws['!ref']); | ||||
| 		range.s.c = _range.s.c; | ||||
| 		range.s.r = _range.s.r; | ||||
| 		range.e.c = Math.max(range.e.c, _range.e.c); | ||||
| 		range.e.r = Math.max(range.e.r, _range.e.r); | ||||
| 		if(_R == -1) range.e.r = _R = _range.e.r + 1; | ||||
| 	} | ||||
| 	for(var R = 0; R != data.length; ++R) { | ||||
| 		for(var C = 0; C != data[R].length; ++C) { | ||||
| 			if(typeof data[R][C] === 'undefined') continue; | ||||
| 			var cell = ({v: data[R][C] }); | ||||
| 			if(Array.isArray(cell.v)) { cell.f = data[R][C][1]; cell.v = cell.v[0]; } | ||||
| 			if(range.s.r > R) range.s.r = R; | ||||
| 			if(range.s.c > C) range.s.c = C; | ||||
| 			if(range.e.r < R) range.e.r = R; | ||||
| 			if(range.e.c < C) range.e.c = C; | ||||
| 			var __R = _R + R, __C = _C + C; | ||||
| 			if(range.s.r > __R) range.s.r = __R; | ||||
| 			if(range.s.c > __C) range.s.c = __C; | ||||
| 			if(range.e.r < __R) range.e.r = __R; | ||||
| 			if(range.e.c < __C) range.e.c = __C; | ||||
| 			if(cell.v === null) { if(cell.f) cell.t = 'n'; else if(!o.cellStubs) continue; else cell.t = 'z'; } | ||||
| 			else if(typeof cell.v === 'number') cell.t = 'n'; | ||||
| 			else if(typeof cell.v === 'boolean') cell.t = 'b'; | ||||
| @ -2712,11 +2735,11 @@ function aoa_to_sheet(data, opts) { | ||||
| 				else { cell.t = 'n'; cell.v = datenum(cell.v); cell.w = SSF.format(cell.z, cell.v); } | ||||
| 			} | ||||
| 			else cell.t = 's'; | ||||
| 			if(o.dense) { | ||||
| 				if(!ws[R]) ws[R] = []; | ||||
| 				ws[R][C] = cell; | ||||
| 			if(dense) { | ||||
| 				if(!ws[__R]) ws[__R] = []; | ||||
| 				ws[__R][__C] = cell; | ||||
| 			} else { | ||||
| 				var cell_ref = encode_cell(({c:C,r:R})); | ||||
| 				var cell_ref = encode_cell(({c:__C,r:__R})); | ||||
| 				ws[cell_ref] = cell; | ||||
| 			} | ||||
| 		} | ||||
| @ -2724,6 +2747,7 @@ function aoa_to_sheet(data, opts) { | ||||
| 	if(range.s.c < 10000000) ws['!ref'] = encode_range(range); | ||||
| 	return ws; | ||||
| } | ||||
| function aoa_to_sheet(data, opts) { return sheet_add_aoa(null, data, opts); } | ||||
| 
 | ||||
| function write_UInt32LE(x, o) { | ||||
| 	if(!o) o = new_buf(4); | ||||
| @ -4047,6 +4071,7 @@ if(!Props.hasOwnProperty(k)) return; | ||||
| 	}); | ||||
| 	if(Custprops) keys(Custprops).forEach(function(k) { | ||||
| if(!Custprops.hasOwnProperty(k)) return; | ||||
| 		if(Props && Props.hasOwnProperty(k)) return; | ||||
| 		var m = Custprops[k]; | ||||
| 		var t = "string"; | ||||
| 		if(typeof m == 'number') { t = "float"; m = String(m); } | ||||
| @ -5224,7 +5249,7 @@ function parse_ShrFmla(blob, length, opts) { | ||||
| 	blob.l++; | ||||
| 	var cUse = blob.read_shift(1); | ||||
| 	length -= 8; | ||||
| 	return [parse_SharedParsedFormula(blob, length, opts), cUse]; | ||||
| 	return [parse_SharedParsedFormula(blob, length, opts), cUse, ref]; | ||||
| } | ||||
| 
 | ||||
| /* 2.4.4 TODO */ | ||||
| @ -7097,10 +7122,8 @@ function parse_DataSpaceDefinition(blob, length) { | ||||
| function parse_TransformInfoHeader(blob, length) { | ||||
| 	var o = {}; | ||||
| 	var len = blob.read_shift(4); | ||||
| 	var tgt = blob.l + len - 4; | ||||
| 	blob.l += 4; // must be 0x1
 | ||||
| 	o.id = blob.read_shift(0, 'lpp4'); | ||||
| 	if(tgt != blob.l) throw new Error("Bad TransformInfoHeader record: " + blob.l + " != " + tgt); | ||||
| 	o.name = blob.read_shift(0, 'lpp4'); | ||||
| 	o.R = parse_CRYPTOVersion(blob, 4); | ||||
| 	o.U = parse_CRYPTOVersion(blob, 4); | ||||
| @ -9089,10 +9112,11 @@ var crefregex = /(^|[^._A-Z0-9])([$]?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A | ||||
| var a1_to_rc =(function(){ | ||||
| 	return function a1_to_rc(fstr, base) { | ||||
| 		return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5, off, str) { | ||||
| 			/* TODO: handle fixcol / fixrow */ | ||||
| 			var c = decode_col($3) - base.c; | ||||
| 			var r = decode_row($5) - base.r; | ||||
| 			return $1 + "R" + (r == 0 ? "" : "[" + r + "]") + "C" + (c == 0 ? "" : "[" + c + "]"); | ||||
| 			var c = decode_col($3) - ($2 ? 0 : base.c); | ||||
| 			var r = decode_row($5) - ($4 ? 0 : base.r); | ||||
| 			var R = (r == 0 ? "" : !$4 ? "[" + r + "]" : (r+1)); | ||||
| 			var C = (c == 0 ? "" : !$2 ? "[" + c + "]" : (c+1)); | ||||
| 			return $1 + "R" + R + "C" + C; | ||||
| 		}); | ||||
| 	}; | ||||
| })(); | ||||
| @ -9188,7 +9212,7 @@ function parse_RgceLocRel(blob, length, opts) { | ||||
| 	if(biff >= 2 && biff <= 5) return parse_RgceLocRel_BIFF2(blob, length, opts); | ||||
| 	var r = blob.read_shift(biff >= 12 ? 4 : 2); | ||||
| 	var cl = blob.read_shift(2); | ||||
| 	var cRel = (cl & 0x8000) >> 15, rRel = (cl & 0x4000) >> 14; | ||||
| 	var cRel = (cl & 0x4000) >> 14, rRel = (cl & 0x8000) >> 15; | ||||
| 	cl &= 0x3FFF; | ||||
| 	if(rRel == 1) while(r > 0x7FFFF) r -= 0x100000; | ||||
| 	if(cRel == 1) while(cl > 0x1FFF) cl = cl - 0x4000; | ||||
| @ -9960,7 +9984,7 @@ function stringify_formula(formula/*Array<any>*/, range, cell, supbooks, opts) { | ||||
| 			case 'PtgErr': /* 2.5.198.57 */ | ||||
| 				stack.push(f[1]); break; | ||||
| 			case 'PtgAreaN': /* 2.5.198.31 TODO */ | ||||
| 				type = f[1][0]; r = shift_range_xls(f[1][1], _range, opts); | ||||
| 				type = f[1][0]; r = shift_range_xls(f[1][1], cell ? {s:cell} : _range, opts); | ||||
| 				stack.push(encode_range_xls((r), opts)); | ||||
| 				break; | ||||
| 			case 'PtgArea': /* 2.5.198.27 TODO: fixed points */ | ||||
| @ -14263,7 +14287,7 @@ for(var cma = c; cma <= cc; ++cma) { | ||||
| 			var _NamedRange = parsexmltag(Rn[0]); | ||||
| 			var _DefinedName = ({ | ||||
| 				Name: _NamedRange.Name, | ||||
| 				Ref: rc_to_a1(_NamedRange.RefersTo.substr(1)) | ||||
| 				Ref: rc_to_a1(_NamedRange.RefersTo.substr(1), {r:0, c:0}) | ||||
| 			}); | ||||
| 			if(Workbook.Sheets.length>0) _DefinedName.Sheet=Workbook.Sheets.length-1; | ||||
| Workbook.Names.push(_DefinedName); | ||||
| @ -14791,6 +14815,35 @@ function write_sty_xlml(wb, opts) { | ||||
| 	}); | ||||
| 	return writextag("Styles", styles.join("")); | ||||
| } | ||||
| function write_name_xlml(n) { return writextag("NamedRange", null, {"ss:Name": n.Name, "ss:RefersTo":"=" + a1_to_rc(n.Ref, {r:0,c:0})}); } | ||||
| function write_names_xlml(wb, opts) { | ||||
| 	if(!((wb||{}).Workbook||{}).Names) return ""; | ||||
| var names = wb.Workbook.Names; | ||||
| 	var out = []; | ||||
| 	for(var i = 0; i < names.length; ++i) { | ||||
| 		var n = names[i]; | ||||
| 		if(n.Sheet != null) continue; | ||||
| 		if(n.Name.match(/^_xlfn\./)) continue; | ||||
| 		out.push(write_name_xlml(n)); | ||||
| 	} | ||||
| 	return writextag("Names", out.join("")); | ||||
| } | ||||
| function write_ws_xlml_names(ws, opts, idx, wb) { | ||||
| 	if(!ws) return ""; | ||||
| 	if(!((wb||{}).Workbook||{}).Names) return ""; | ||||
| var names = wb.Workbook.Names; | ||||
| 	var out = []; | ||||
| 	outer: for(var i = 0; i < names.length; ++i) { | ||||
| 		var n = names[i]; | ||||
| 		if(n.Sheet != idx) continue; | ||||
| 		/*switch(n.Name) { | ||||
| 			case "_": continue; | ||||
| 		}*/ | ||||
| 		if(n.Name.match(/^_xlfn\./)) continue; | ||||
| 		out.push(write_name_xlml(n)); | ||||
| 	} | ||||
| 	return out.join(""); | ||||
| } | ||||
| /* WorksheetOptions */ | ||||
| function write_ws_xlml_wsopts(ws, opts, idx, wb) { | ||||
| 	if(!ws) return ""; | ||||
| @ -14909,7 +14962,7 @@ function write_ws_xlml_comment(comments) { | ||||
| 	}).join(""); | ||||
| } | ||||
| function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr){ | ||||
| 	if(!cell || cell.v == undefined && cell.f == undefined) return "<Cell></Cell>"; | ||||
| 	if(!cell || cell.v == undefined && cell.f == undefined) return ""; | ||||
| 
 | ||||
| 	var attr = {}; | ||||
| 	if(cell.f) attr["ss:Formula"] = "=" + escapexml(a1_to_rc(cell.f, addr)); | ||||
| @ -14939,11 +14992,12 @@ function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr){ | ||||
| 		case 'b': t = 'Boolean'; p = (cell.v ? "1" : "0"); break; | ||||
| 		case 'e': t = 'Error'; p = BErr[cell.v]; break; | ||||
| 		case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); if(cell.z == null) cell.z = cell.z || SSF._table[14]; break; | ||||
| 		case 's': t = 'String'; p = escapexml(cell.v||""); break; | ||||
| 		case 's': t = 'String'; p = escapexlml(cell.v||""); break; | ||||
| 	} | ||||
| 	/* TODO: cell style */ | ||||
| 	var os = get_cell_style(opts.cellXfs, cell, opts); | ||||
| 	attr["ss:StyleID"] = "s" + (21+os); | ||||
| 	attr["ss:Index"] = addr.c + 1; | ||||
| 	var _v = (cell.v != null ? p : ""); | ||||
| 	var m = '<Data ss:Type="' + t + '">' + _v + '</Data>'; | ||||
| 
 | ||||
| @ -15003,8 +15057,11 @@ function write_ws_xlml(idx, opts, wb) { | ||||
| 	var s = wb.SheetNames[idx]; | ||||
| 	var ws = wb.Sheets[s]; | ||||
| 
 | ||||
| 	var t = ws ? write_ws_xlml_names(ws, opts, idx, wb) : ""; | ||||
| 	if(t.length > 0) o.push("<Names>" + t + "</Names>"); | ||||
| 
 | ||||
| 	/* Table */ | ||||
| 	var t = ws ? write_ws_xlml_table(ws, opts, idx, wb) : ""; | ||||
| 	t = ws ? write_ws_xlml_table(ws, opts, idx, wb) : ""; | ||||
| 	if(t.length > 0) o.push("<Table>" + t + "</Table>"); | ||||
| 
 | ||||
| 	/* WorksheetOptions */ | ||||
| @ -15027,9 +15084,11 @@ function write_xlml(wb, opts) { | ||||
| 	d.push(write_props_xlml(wb, opts)); | ||||
| 	d.push(write_wb_xlml(wb, opts)); | ||||
| 	d.push(""); | ||||
| 	d.push(""); | ||||
| 	for(var i = 0; i < wb.SheetNames.length; ++i) | ||||
| 		d.push(writextag("Worksheet", write_ws_xlml(i, opts, wb), {"ss:Name":escapexml(wb.SheetNames[i])})); | ||||
| 	d[2] = write_sty_xlml(wb, opts); | ||||
| 	d[3] = write_names_xlml(wb, opts); | ||||
| 	return XML_HEADER + writextag("Workbook", d.join(""), { | ||||
| 		'xmlns':      XLMLNS.ss, | ||||
| 		'xmlns:o':    XLMLNS.o, | ||||
| @ -15144,7 +15203,7 @@ function parse_workbook(blob, options) { | ||||
| 	var cur_sheet = ""; | ||||
| 	var Preamble = {}; | ||||
| 	var lastcell, last_cell = "", cc, cmnt, rngC, rngR; | ||||
| 	var shared_formulae = {}; | ||||
| 	var sharedf = {}; | ||||
| 	var arrayf = []; | ||||
| 	var temp_val; | ||||
| 	var country; | ||||
| @ -15183,13 +15242,10 @@ function parse_workbook(blob, options) { | ||||
| 		} | ||||
| 		if(options.cellFormula && line.f) { | ||||
| 			for(var afi = 0; afi < arrayf.length; ++afi) { | ||||
| 				if(arrayf[afi][0].s.c > cell.c) continue; | ||||
| 				if(arrayf[afi][0].s.r > cell.r) continue; | ||||
| 				if(arrayf[afi][0].e.c < cell.c) continue; | ||||
| 				if(arrayf[afi][0].e.r < cell.r) continue; | ||||
| 				if(arrayf[afi][0].s.c > cell.c || arrayf[afi][0].s.r > cell.r) continue; | ||||
| 				if(arrayf[afi][0].e.c < cell.c || arrayf[afi][0].e.r < cell.r) continue; | ||||
| 				line.F = encode_range(arrayf[afi][0]); | ||||
| 				if(arrayf[afi][0].s.c != cell.c) delete line.f; | ||||
| 				if(arrayf[afi][0].s.r != cell.r) delete line.f; | ||||
| 				if(arrayf[afi][0].s.c != cell.c || arrayf[afi][0].s.r != cell.r) delete line.f; | ||||
| 				if(line.f) line.f = "" + stringify_formula(arrayf[afi][1], range, cell, supbooks, opts); | ||||
| 				break; | ||||
| 			} | ||||
| @ -15206,7 +15262,7 @@ function parse_workbook(blob, options) { | ||||
| 		enc: false, // encrypted
 | ||||
| 		sbcch: 0, // cch in the preceding SupBook
 | ||||
| 		snames: [], // sheetnames
 | ||||
| 		sharedf: shared_formulae, // shared formulae by address
 | ||||
| 		sharedf: sharedf, // shared formulae by address
 | ||||
| 		arrayf: arrayf, // array formulae array
 | ||||
| 		rrtabid: [], // RRTabId
 | ||||
| 		lastuser: "", // Last User from WriteAccess
 | ||||
| @ -15262,6 +15318,7 @@ function parse_workbook(blob, options) { | ||||
| 			if(R.n === 'EOF') val = R.f(blob, length, opts); | ||||
| 			else val = slurp(R, blob, length, opts); | ||||
| 			var Rn = R.n; | ||||
| 			if(file_depth == 0 && Rn != 'BOF') continue; | ||||
| 			/* nested switch statements to workaround V8 128 limit */ | ||||
| 			switch(Rn) { | ||||
| 				/* Workbook Options */ | ||||
| @ -15291,16 +15348,17 @@ wb.opts.Date1904 = Workbook.WBProps.date1904 = val; break; | ||||
| 				case 'RRTabId': opts.rrtabid = val; break; | ||||
| 				case 'WinProtect': opts.winlocked = val; break; | ||||
| 				case 'Template': break; // TODO
 | ||||
| 				case 'RefreshAll': wb.opts.RefreshAll = val; break; | ||||
| 				case 'BookBool': break; // TODO
 | ||||
| 				case 'UsesELFs': break; | ||||
| 				case 'MTRSettings': break; | ||||
| 				case 'CalcCount': wb.opts.CalcCount = val; break; | ||||
| 				case 'CalcDelta': wb.opts.CalcDelta = val; break; | ||||
| 				case 'CalcIter': wb.opts.CalcIter = val; break; | ||||
| 				case 'CalcMode': wb.opts.CalcMode = val; break; | ||||
| 				case 'CalcPrecision': wb.opts.CalcPrecision = val; break; | ||||
| 				case 'CalcSaveRecalc': wb.opts.CalcSaveRecalc = val; break; | ||||
| 				case 'RefreshAll': | ||||
| 				case 'CalcCount': | ||||
| 				case 'CalcDelta': | ||||
| 				case 'CalcIter': | ||||
| 				case 'CalcMode': | ||||
| 				case 'CalcPrecision': | ||||
| 				case 'CalcSaveRecalc': | ||||
| 					wb.opts[Rn] = val; break; | ||||
| 				case 'CalcRefMode': opts.CalcRefMode = val; break; // TODO: implement R1C1
 | ||||
| 				case 'Uncalced': break; | ||||
| 				case 'ForceFullCalculation': wb.opts.FullCalc = val; break; | ||||
| @ -15442,7 +15500,7 @@ wb.opts.Date1904 = Workbook.WBProps.date1904 = val; break; | ||||
| 						if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') { | ||||
| 							var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1]; | ||||
| 							var _fe = encode_cell({r:_fr, c:_fc}); | ||||
| 							if(shared_formulae[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); | ||||
| 							if(sharedf[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); | ||||
| 							else temp_val.F = ((options.dense ? (out[_fr]||[])[_fc]: out[_fe]) || {}).F; | ||||
| 						} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); | ||||
| 					} | ||||
| @ -15482,7 +15540,7 @@ wb.opts.Date1904 = Workbook.WBProps.date1904 = val; break; | ||||
| 					if(last_cell) { | ||||
| 						/* TODO: capture range */ | ||||
| 						if(!last_formula) break; /* technically unreachable */ | ||||
| 						shared_formulae[encode_cell(last_formula.cell)]= val[0]; | ||||
| 						sharedf[encode_cell(last_formula.cell)]= val[0]; | ||||
| 						cc = options.dense ? (out[last_formula.cell.r]||[])[last_formula.cell.c] : out[encode_cell(last_formula.cell)]; | ||||
| 						(cc||{}).f = ""+stringify_formula(val[0], range, lastcell, supbooks, opts); | ||||
| 					} | ||||
| @ -19217,11 +19275,26 @@ function sheet_to_formulae(sheet) { | ||||
| 	return cmds; | ||||
| } | ||||
| 
 | ||||
| function json_to_sheet(js, opts) { | ||||
| function sheet_add_json(_ws, js, opts) { | ||||
| 	var o = opts || {}; | ||||
| 	var ws = ({}); | ||||
| 	var offset = +!o.skipHeader; | ||||
| 	var ws = _ws || ({}); | ||||
| 	var _R = 0, _C = 0; | ||||
| 	if(ws && o.origin != null) { | ||||
| 		if(typeof o.origin == 'number') _R = o.origin; | ||||
| 		else { | ||||
| 			var _origin = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin; | ||||
| 			_R = _origin.r; _C = _origin.c; | ||||
| 		} | ||||
| 	} | ||||
| 	var cell; | ||||
| 	var range = ({s: {c:0, r:0}, e: {c:0, r:js.length}}); | ||||
| 	var range = ({s: {c:0, r:0}, e: {c:_C, r:_R + js.length - 1 + offset}}); | ||||
| 	if(ws['!ref']) { | ||||
| 		var _range = safe_decode_range(ws['!ref']); | ||||
| 		range.e.c = Math.max(range.e.c, _range.e.c); | ||||
| 		range.e.r = Math.max(range.e.r, _range.e.r); | ||||
| 		if(_R == -1) { _R = range.e.r + 1; range.e.r = _R + js.length - 1 + offset; } | ||||
| 	} | ||||
| 	var hdr = o.header || [], C = 0; | ||||
| 
 | ||||
| 	js.forEach(function (JS, R) { | ||||
| @ -19238,15 +19311,17 @@ function json_to_sheet(js, opts) { | ||||
| 				if(!o.cellDates) { t = 'n'; v = datenum(v); } | ||||
| 				z = o.dateNF || SSF._table[14]; | ||||
| 			} | ||||
| 			ws[encode_cell({c:C,r:R+1})] = cell = ({t:t, v:v}); | ||||
| 			ws[encode_cell({c:_C + C,r:_R + R + offset})] = cell = ({t:t, v:v}); | ||||
| 			if(z) cell.z = z; | ||||
| 		}); | ||||
| 	}); | ||||
| 	range.e.c = hdr.length - 1; | ||||
| 	for(C = 0; C < hdr.length; ++C) ws[encode_col(C) + "1"] = {t:'s', v:hdr[C]}; | ||||
| 	range.e.c = Math.max(range.e.c, _C + hdr.length - 1); | ||||
| 	var __R = encode_row(_R); | ||||
| 	if(offset) for(C = 0; C < hdr.length; ++C) ws[encode_col(C + _C) + __R] = {t:'s', v:hdr[C]}; | ||||
| 	ws['!ref'] = encode_range(range); | ||||
| 	return ws; | ||||
| } | ||||
| function json_to_sheet(js, opts) { return sheet_add_json(null, js, opts); } | ||||
| 
 | ||||
| var utils = { | ||||
| 	encode_col: encode_col, | ||||
| @ -19263,6 +19338,8 @@ var utils = { | ||||
| 	make_csv: sheet_to_csv, | ||||
| 	make_json: sheet_to_json, | ||||
| 	make_formulae: sheet_to_formulae, | ||||
| 	sheet_add_aoa: sheet_add_aoa, | ||||
| 	sheet_add_json: sheet_add_json, | ||||
| 	aoa_to_sheet: aoa_to_sheet, | ||||
| 	json_to_sheet: json_to_sheet, | ||||
| 	table_to_sheet: parse_dom_table, | ||||
|  | ||||
							
								
								
									
										24
									
								
								dist/xlsx.min.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										24
									
								
								dist/xlsx.min.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2
									
								
								dist/xlsx.min.map
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										2
									
								
								dist/xlsx.min.map
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @ -4,7 +4,7 @@ The [`demos` directory](demos/) includes sample projects for: | ||||
| 
 | ||||
| **Frameworks and APIs** | ||||
| - [`angular 1.x`](demos/angular/) | ||||
| - [`angular 2.x / 4.x / 5.x`](demos/angular2/) | ||||
| - [`angular 2 / 4 / 5 and ionic`](demos/angular2/) | ||||
| - [`meteor`](demos/meteor/) | ||||
| - [`react and react-native`](demos/react/) | ||||
| - [`vue 2.x and weex`](demos/vue/) | ||||
|  | ||||
| @ -37,6 +37,8 @@ Utilities are available in the `XLSX.utils` object and are described in the | ||||
| - `aoa_to_sheet` converts an array of arrays of JS data to a worksheet. | ||||
| - `json_to_sheet` converts an array of JS objects to a worksheet. | ||||
| - `table_to_sheet` converts a DOM TABLE element to a worksheet. | ||||
| - `sheet_add_aoa` adds an array of arrays of JS data to an existing worksheet. | ||||
| - `sheet_add_json` adds an array of JS objects to an existing worksheet. | ||||
| 
 | ||||
| 
 | ||||
| **Exporting:** | ||||
|  | ||||
| @ -42,6 +42,61 @@ var ws = XLSX.utils.aoa_to_sheet([ | ||||
| ``` | ||||
| </details> | ||||
| 
 | ||||
| `XLSX.utils.sheet_add_aoa` takes an array of arrays of JS values and updates an | ||||
| existing worksheet object.  It follows the same process as `aoa_to_sheet` and | ||||
| accepts an options argument: | ||||
| 
 | ||||
| | Option Name |  Default | Description                                         | | ||||
| | :---------- | :------: | :-------------------------------------------------- | | ||||
| |`dateNF`     |  FMT 14  | Use specified date format in string output          | | ||||
| |`cellDates`  |  false   | Store dates as type `d` (default is `n`)            | | ||||
| |`sheetStubs` |  false   | Create cell objects of type `z` for `null` values   | | ||||
| |`origin`     |          | Use specified cell as starting point (see below)    | | ||||
| 
 | ||||
| `origin` is expected to be one of: | ||||
| 
 | ||||
| | `origin`         | Description                                               | | ||||
| | :--------------- | :-------------------------------------------------------- | | ||||
| | (cell object)    | Use specified cell (cell object)                          | | ||||
| | (string)         | Use specified cell (A1-style cell)                        | | ||||
| | (number >= 0)    | Start from the first column at specified row (0-indexed)  | | ||||
| | -1               | Append to bottom of worksheet starting on first column    | | ||||
| | (default)        | Start from cell A1                                        | | ||||
| 
 | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>Examples</b> (click to show)</summary> | ||||
| 
 | ||||
| Consider the worksheet: | ||||
| 
 | ||||
| ``` | ||||
| XXX| A | B | C | D | E | F | G | | ||||
| ---+---+---+---+---+---+---+---+ | ||||
|  1 | S | h | e | e | t | J | S | | ||||
|  2 | 1 | 2 |   |   | 5 | 6 | 7 | | ||||
|  3 | 2 | 3 |   |   | 6 | 7 | 8 | | ||||
|  4 | 3 | 4 |   |   | 7 | 8 | 9 | | ||||
|  5 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | | ||||
| ``` | ||||
| 
 | ||||
| This worksheet can be built up in the order `A1:G1, A2:B4, E2:G4, A5:G5`: | ||||
| 
 | ||||
| ```js | ||||
| /* Initial row */ | ||||
| var ws = XLSX.utils.aoa_to_sheet([ "SheetJS".split("") ]); | ||||
| 
 | ||||
| /* Write data starting at A2 */ | ||||
| XLSX.utils.sheet_add_aoa(ws, [[1,2], [2,3], [3,4]], {origin: "A2"}); | ||||
| 
 | ||||
| /* Write data starting at E2 */ | ||||
| XLSX.utils.sheet_add_aoa(ws, [[5,6,7], [6,7,8], [7,8,9]], {origin:{r:1, c:4}}); | ||||
| 
 | ||||
| /* Append row */ | ||||
| XLSX.utils.sheet_add_aoa(ws, [[4,5,6,7,8,9,0]], {origin: -1}); | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| ### Array of Objects Input | ||||
| 
 | ||||
| `XLSX.utils.json_to_sheet` takes an array of objects and returns a worksheet | ||||
| @ -54,19 +109,95 @@ default column order is determined by the first appearance of the field using | ||||
| |`header`     |          | Use specified column order (default `Object.keys`)  | | ||||
| |`dateNF`     |  FMT 14  | Use specified date format in string output          | | ||||
| |`cellDates`  |  false   | Store dates as type `d` (default is `n`)            | | ||||
| |`skipHeader` |  false   | If true, do not include header row in output        | | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>Examples</b> (click to show)</summary> | ||||
| 
 | ||||
| The original sheet cannot be reproduced because JS object keys must be unique. | ||||
| After replacing the second `e` and `S` with `e_1` and `S_1`: | ||||
| The original sheet cannot be reproduced in the obvious way since JS object keys | ||||
| must be unique. After replacing the second `e` and `S` with `e_1` and `S_1`: | ||||
| 
 | ||||
| ```js | ||||
| var ws = XLSX.utils.json_to_sheet([ | ||||
|   {S:1,h:2,e:3,e_1:4,t:5,J:6,S_1:7}, | ||||
|   {S:2,h:3,e:4,e_1:5,t:6,J:7,S_1:8} | ||||
|   { S:1, h:2, e:3, e_1:4, t:5, J:6, S_1:7 }, | ||||
|   { S:2, h:3, e:4, e_1:5, t:6, J:7, S_1:8 } | ||||
| ], {header:["S","h","e","e_1","t","J","S_1"]}); | ||||
| ``` | ||||
| 
 | ||||
| Alternatively, the header row can be skipped: | ||||
| 
 | ||||
| ```js | ||||
| var ws = XLSX.utils.json_to_sheet([ | ||||
|   { A:"S", B:"h", C:"e", D:"e", E:"t", F:"J", G:"S" }, | ||||
|   { A: 1,  B: 2,  C: 3,  D: 4,  E: 5,  F: 6,  G: 7  }, | ||||
|   { A: 2,  B: 3,  C: 4,  D: 5,  E: 6,  F: 7,  G: 8  } | ||||
| ], {header:["A","B","C","D","E","F","G"], skipHeader:true}); | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| `XLSX.utils.sheet_add_json` takes an array of objects and updates an existing | ||||
| worksheet object.  It follows the same process as `json_to_sheet` and accepts | ||||
| an options argument: | ||||
| 
 | ||||
| | Option Name |  Default | Description                                         | | ||||
| | :---------- | :------: | :-------------------------------------------------- | | ||||
| |`header`     |          | Use specified column order (default `Object.keys`)  | | ||||
| |`dateNF`     |  FMT 14  | Use specified date format in string output          | | ||||
| |`cellDates`  |  false   | Store dates as type `d` (default is `n`)            | | ||||
| |`skipHeader` |  false   | If true, do not include header row in output        | | ||||
| |`origin`     |          | Use specified cell as starting point (see below)    | | ||||
| 
 | ||||
| `origin` is expected to be one of: | ||||
| 
 | ||||
| | `origin`         | Description                                               | | ||||
| | :--------------- | :-------------------------------------------------------- | | ||||
| | (cell object)    | Use specified cell (cell object)                          | | ||||
| | (string)         | Use specified cell (A1-style cell)                        | | ||||
| | (number >= 0)    | Start from the first column at specified row (0-indexed)  | | ||||
| | -1               | Append to bottom of worksheet starting on first column    | | ||||
| | (default)        | Start from cell A1                                        | | ||||
| 
 | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>Examples</b> (click to show)</summary> | ||||
| 
 | ||||
| Consider the worksheet: | ||||
| 
 | ||||
| ``` | ||||
| XXX| A | B | C | D | E | F | G | | ||||
| ---+---+---+---+---+---+---+---+ | ||||
|  1 | S | h | e | e | t | J | S | | ||||
|  2 | 1 | 2 |   |   | 5 | 6 | 7 | | ||||
|  3 | 2 | 3 |   |   | 6 | 7 | 8 | | ||||
|  4 | 3 | 4 |   |   | 7 | 8 | 9 | | ||||
|  5 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | | ||||
| ``` | ||||
| 
 | ||||
| This worksheet can be built up in the order `A1:G1, A2:B4, E2:G4, A5:G5`: | ||||
| 
 | ||||
| ```js | ||||
| /* Initial row */ | ||||
| var ws = XLSX.utils.json_to_sheet([ | ||||
|   { A: "S", B: "h", C: "e", D: "e", E: "t", F: "J", G: "S" } | ||||
| ], {header: ["A", "B", "C", "D", "E", "F", "G"], skipHeader: true}); | ||||
| 
 | ||||
| /* Write data starting at A2 */ | ||||
| XLSX.utils.sheet_add_json(ws, [ | ||||
|   { A: 1, B: 2 }, { A: 2, B: 3 }, { A: 3, B: 4 } | ||||
| ], {skipHeader: true, origin: "A2"}); | ||||
| 
 | ||||
| /* Write data starting at E2 */ | ||||
| XLSX.utils.sheet_add_json(ws, [ | ||||
|   { A: 5, B: 6, C: 7 }, { A: 6, B: 7, C: 8 }, { A: 7, B: 8, C: 9 } | ||||
| ], {skipHeader: true, origin: { r: 1, c: 4 }, header: [ "A", "B", "C" ]}); | ||||
| 
 | ||||
| /* Append row */ | ||||
| XLSX.utils.sheet_add_json(ws, [ | ||||
|   { A: 4, B: 5, C: 6, D: 7, E: 8, F: 9, G: 0 } | ||||
| ], {header: ["A", "B", "C", "D", "E", "F", "G"], skipHeader: true, origin: -1}); | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| ### HTML Table Input | ||||
|  | ||||
| @ -181,7 +181,7 @@ The [`demos` directory](demos/) includes sample projects for: | ||||
| 
 | ||||
| **Frameworks and APIs** | ||||
| - [`angular 1.x`](demos/angular/) | ||||
| - [`angular 2.x / 4.x / 5.x`](demos/angular2/) | ||||
| - [`angular 2 / 4 / 5 and ionic`](demos/angular2/) | ||||
| - [`meteor`](demos/meteor/) | ||||
| - [`react and react-native`](demos/react/) | ||||
| - [`vue 2.x and weex`](demos/vue/) | ||||
| @ -658,6 +658,8 @@ Utilities are available in the `XLSX.utils` object and are described in the | ||||
| - `aoa_to_sheet` converts an array of arrays of JS data to a worksheet. | ||||
| - `json_to_sheet` converts an array of JS objects to a worksheet. | ||||
| - `table_to_sheet` converts a DOM TABLE element to a worksheet. | ||||
| - `sheet_add_aoa` adds an array of arrays of JS data to an existing worksheet. | ||||
| - `sheet_add_json` adds an array of JS objects to an existing worksheet. | ||||
| 
 | ||||
| 
 | ||||
| **Exporting:** | ||||
| @ -1604,6 +1606,58 @@ var ws = XLSX.utils.aoa_to_sheet([ | ||||
| ]); | ||||
| ``` | ||||
| 
 | ||||
| `XLSX.utils.sheet_add_aoa` takes an array of arrays of JS values and updates an | ||||
| existing worksheet object.  It follows the same process as `aoa_to_sheet` and | ||||
| accepts an options argument: | ||||
| 
 | ||||
| | Option Name |  Default | Description                                         | | ||||
| | :---------- | :------: | :-------------------------------------------------- | | ||||
| |`dateNF`     |  FMT 14  | Use specified date format in string output          | | ||||
| |`cellDates`  |  false   | Store dates as type `d` (default is `n`)            | | ||||
| |`sheetStubs` |  false   | Create cell objects of type `z` for `null` values   | | ||||
| |`origin`     |          | Use specified cell as starting point (see below)    | | ||||
| 
 | ||||
| `origin` is expected to be one of: | ||||
| 
 | ||||
| | `origin`         | Description                                               | | ||||
| | :--------------- | :-------------------------------------------------------- | | ||||
| | (cell object)    | Use specified cell (cell object)                          | | ||||
| | (string)         | Use specified cell (A1-style cell)                        | | ||||
| | (number >= 0)    | Start from the first column at specified row (0-indexed)  | | ||||
| | -1               | Append to bottom of worksheet starting on first column    | | ||||
| | (default)        | Start from cell A1                                        | | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| Consider the worksheet: | ||||
| 
 | ||||
| ``` | ||||
| XXX| A | B | C | D | E | F | G | | ||||
| ---+---+---+---+---+---+---+---+ | ||||
|  1 | S | h | e | e | t | J | S | | ||||
|  2 | 1 | 2 |   |   | 5 | 6 | 7 | | ||||
|  3 | 2 | 3 |   |   | 6 | 7 | 8 | | ||||
|  4 | 3 | 4 |   |   | 7 | 8 | 9 | | ||||
|  5 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | | ||||
| ``` | ||||
| 
 | ||||
| This worksheet can be built up in the order `A1:G1, A2:B4, E2:G4, A5:G5`: | ||||
| 
 | ||||
| ```js | ||||
| /* Initial row */ | ||||
| var ws = XLSX.utils.aoa_to_sheet([ "SheetJS".split("") ]); | ||||
| 
 | ||||
| /* Write data starting at A2 */ | ||||
| XLSX.utils.sheet_add_aoa(ws, [[1,2], [2,3], [3,4]], {origin: "A2"}); | ||||
| 
 | ||||
| /* Write data starting at E2 */ | ||||
| XLSX.utils.sheet_add_aoa(ws, [[5,6,7], [6,7,8], [7,8,9]], {origin:{r:1, c:4}}); | ||||
| 
 | ||||
| /* Append row */ | ||||
| XLSX.utils.sheet_add_aoa(ws, [[4,5,6,7,8,9,0]], {origin: -1}); | ||||
| ``` | ||||
| 
 | ||||
| 
 | ||||
| ### Array of Objects Input | ||||
| 
 | ||||
| `XLSX.utils.json_to_sheet` takes an array of objects and returns a worksheet | ||||
| @ -1616,18 +1670,91 @@ default column order is determined by the first appearance of the field using | ||||
| |`header`     |          | Use specified column order (default `Object.keys`)  | | ||||
| |`dateNF`     |  FMT 14  | Use specified date format in string output          | | ||||
| |`cellDates`  |  false   | Store dates as type `d` (default is `n`)            | | ||||
| |`skipHeader` |  false   | If true, do not include header row in output        | | ||||
| 
 | ||||
| 
 | ||||
| The original sheet cannot be reproduced because JS object keys must be unique. | ||||
| After replacing the second `e` and `S` with `e_1` and `S_1`: | ||||
| The original sheet cannot be reproduced in the obvious way since JS object keys | ||||
| must be unique. After replacing the second `e` and `S` with `e_1` and `S_1`: | ||||
| 
 | ||||
| ```js | ||||
| var ws = XLSX.utils.json_to_sheet([ | ||||
|   {S:1,h:2,e:3,e_1:4,t:5,J:6,S_1:7}, | ||||
|   {S:2,h:3,e:4,e_1:5,t:6,J:7,S_1:8} | ||||
|   { S:1, h:2, e:3, e_1:4, t:5, J:6, S_1:7 }, | ||||
|   { S:2, h:3, e:4, e_1:5, t:6, J:7, S_1:8 } | ||||
| ], {header:["S","h","e","e_1","t","J","S_1"]}); | ||||
| ``` | ||||
| 
 | ||||
| Alternatively, the header row can be skipped: | ||||
| 
 | ||||
| ```js | ||||
| var ws = XLSX.utils.json_to_sheet([ | ||||
|   { A:"S", B:"h", C:"e", D:"e", E:"t", F:"J", G:"S" }, | ||||
|   { A: 1,  B: 2,  C: 3,  D: 4,  E: 5,  F: 6,  G: 7  }, | ||||
|   { A: 2,  B: 3,  C: 4,  D: 5,  E: 6,  F: 7,  G: 8  } | ||||
| ], {header:["A","B","C","D","E","F","G"], skipHeader:true}); | ||||
| ``` | ||||
| 
 | ||||
| 
 | ||||
| `XLSX.utils.sheet_add_json` takes an array of objects and updates an existing | ||||
| worksheet object.  It follows the same process as `json_to_sheet` and accepts | ||||
| an options argument: | ||||
| 
 | ||||
| | Option Name |  Default | Description                                         | | ||||
| | :---------- | :------: | :-------------------------------------------------- | | ||||
| |`header`     |          | Use specified column order (default `Object.keys`)  | | ||||
| |`dateNF`     |  FMT 14  | Use specified date format in string output          | | ||||
| |`cellDates`  |  false   | Store dates as type `d` (default is `n`)            | | ||||
| |`skipHeader` |  false   | If true, do not include header row in output        | | ||||
| |`origin`     |          | Use specified cell as starting point (see below)    | | ||||
| 
 | ||||
| `origin` is expected to be one of: | ||||
| 
 | ||||
| | `origin`         | Description                                               | | ||||
| | :--------------- | :-------------------------------------------------------- | | ||||
| | (cell object)    | Use specified cell (cell object)                          | | ||||
| | (string)         | Use specified cell (A1-style cell)                        | | ||||
| | (number >= 0)    | Start from the first column at specified row (0-indexed)  | | ||||
| | -1               | Append to bottom of worksheet starting on first column    | | ||||
| | (default)        | Start from cell A1                                        | | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| Consider the worksheet: | ||||
| 
 | ||||
| ``` | ||||
| XXX| A | B | C | D | E | F | G | | ||||
| ---+---+---+---+---+---+---+---+ | ||||
|  1 | S | h | e | e | t | J | S | | ||||
|  2 | 1 | 2 |   |   | 5 | 6 | 7 | | ||||
|  3 | 2 | 3 |   |   | 6 | 7 | 8 | | ||||
|  4 | 3 | 4 |   |   | 7 | 8 | 9 | | ||||
|  5 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | | ||||
| ``` | ||||
| 
 | ||||
| This worksheet can be built up in the order `A1:G1, A2:B4, E2:G4, A5:G5`: | ||||
| 
 | ||||
| ```js | ||||
| /* Initial row */ | ||||
| var ws = XLSX.utils.json_to_sheet([ | ||||
|   { A: "S", B: "h", C: "e", D: "e", E: "t", F: "J", G: "S" } | ||||
| ], {header: ["A", "B", "C", "D", "E", "F", "G"], skipHeader: true}); | ||||
| 
 | ||||
| /* Write data starting at A2 */ | ||||
| XLSX.utils.sheet_add_json(ws, [ | ||||
|   { A: 1, B: 2 }, { A: 2, B: 3 }, { A: 3, B: 4 } | ||||
| ], {skipHeader: true, origin: "A2"}); | ||||
| 
 | ||||
| /* Write data starting at E2 */ | ||||
| XLSX.utils.sheet_add_json(ws, [ | ||||
|   { A: 5, B: 6, C: 7 }, { A: 6, B: 7, C: 8 }, { A: 7, B: 8, C: 9 } | ||||
| ], {skipHeader: true, origin: { r: 1, c: 4 }, header: [ "A", "B", "C" ]}); | ||||
| 
 | ||||
| /* Append row */ | ||||
| XLSX.utils.sheet_add_json(ws, [ | ||||
|   { A: 4, B: 5, C: 6, D: 7, E: 8, F: 9, G: 0 } | ||||
| ], {header: ["A", "B", "C", "D", "E", "F", "G"], skipHeader: true, origin: -1}); | ||||
| ``` | ||||
| 
 | ||||
| 
 | ||||
| ### HTML Table Input | ||||
| 
 | ||||
| `XLSX.utils.table_to_sheet` takes a table DOM element and returns a worksheet | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| { | ||||
| 	"name": "xlsx", | ||||
| 	"version": "0.11.16", | ||||
| 	"version": "0.11.17", | ||||
| 	"author": "sheetjs", | ||||
| 	"description": "SheetJS Spreadsheet data parser and writer", | ||||
| 	"keywords": [ | ||||
|  | ||||
							
								
								
									
										14
									
								
								test.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										14
									
								
								test.js
									
									
									
									
									
								
							| @ -675,6 +675,20 @@ describe('API', function() { | ||||
| 		X.utils.book_append_sheet(wb, X.utils.aoa_to_sheet([[1,2,3],[4],[5]])); | ||||
| 		eqarr(wb.SheetNames, ["A","Sheet1","Sheet2","B","Sheet3"]); | ||||
| 	}); | ||||
| 	it('sheet_add_json', function() { | ||||
| 		var ws = X.utils.json_to_sheet([{A:"S", B:"h", C:"e", D:"e", E:"t", F:"J", G:"S"}], {header:["A","B","C","D","E","F","G"], skipHeader:true}); | ||||
| 		X.utils.sheet_add_json(ws, [{A:1, B:2}, {A:2, B:3}, {A:3, B:4}], {skipHeader:true, origin:"A2"}); | ||||
| 		X.utils.sheet_add_json(ws, [{A:5, B:6, C:7}, {A:6, B:7, C:8}, {A:7, B:8, C:9}], {skipHeader:true, origin:{r:1, c:4}, header:["A","B","C"]}); | ||||
| 		X.utils.sheet_add_json(ws, [{A:4, B:5, C:6, D:7, E:8, F:9, G:0}], {header:["A","B","C","D","E","F","G"], skipHeader:true, origin:-1}); | ||||
| 		assert.equal(X.utils.sheet_to_csv(ws).trim(), "S,h,e,e,t,J,S\n1,2,,,5,6,7\n2,3,,,6,7,8\n3,4,,,7,8,9\n4,5,6,7,8,9,0"); | ||||
| 	}); | ||||
| 	it('sheet_add_aoa', function() { | ||||
| 		var ws = X.utils.aoa_to_sheet([ "SheetJS".split("") ]); | ||||
| 		X.utils.sheet_add_aoa(ws, [[1,2], [2,3], [3,4]], {origin: "A2"}); | ||||
| 		X.utils.sheet_add_aoa(ws, [[5,6,7], [6,7,8], [7,8,9]], {origin:{r:1, c:4}}); | ||||
| 		X.utils.sheet_add_aoa(ws, [[4,5,6,7,8,9,0]], {origin: -1}); | ||||
| 		assert.equal(X.utils.sheet_to_csv(ws).trim(), "S,h,e,e,t,J,S\n1,2,,,5,6,7\n2,3,,,6,7,8\n3,4,,,7,8,9\n4,5,6,7,8,9,0"); | ||||
| 	}); | ||||
| }); | ||||
| 
 | ||||
| function coreprop(props) { | ||||
|  | ||||
							
								
								
									
										14
									
								
								tests/core.js
									
									
									
										generated
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										14
									
								
								tests/core.js
									
									
									
										generated
									
									
									
								
							| @ -675,6 +675,20 @@ describe('API', function() { | ||||
| 		X.utils.book_append_sheet(wb, X.utils.aoa_to_sheet([[1,2,3],[4],[5]])); | ||||
| 		eqarr(wb.SheetNames, ["A","Sheet1","Sheet2","B","Sheet3"]); | ||||
| 	}); | ||||
| 	it('sheet_add_json', function() { | ||||
| 		var ws = X.utils.json_to_sheet([{A:"S", B:"h", C:"e", D:"e", E:"t", F:"J", G:"S"}], {header:["A","B","C","D","E","F","G"], skipHeader:true}); | ||||
| 		X.utils.sheet_add_json(ws, [{A:1, B:2}, {A:2, B:3}, {A:3, B:4}], {skipHeader:true, origin:"A2"}); | ||||
| 		X.utils.sheet_add_json(ws, [{A:5, B:6, C:7}, {A:6, B:7, C:8}, {A:7, B:8, C:9}], {skipHeader:true, origin:{r:1, c:4}, header:["A","B","C"]}); | ||||
| 		X.utils.sheet_add_json(ws, [{A:4, B:5, C:6, D:7, E:8, F:9, G:0}], {header:["A","B","C","D","E","F","G"], skipHeader:true, origin:-1}); | ||||
| 		assert.equal(X.utils.sheet_to_csv(ws).trim(), "S,h,e,e,t,J,S\n1,2,,,5,6,7\n2,3,,,6,7,8\n3,4,,,7,8,9\n4,5,6,7,8,9,0"); | ||||
| 	}); | ||||
| 	it('sheet_add_aoa', function() { | ||||
| 		var ws = X.utils.aoa_to_sheet([ "SheetJS".split("") ]); | ||||
| 		X.utils.sheet_add_aoa(ws, [[1,2], [2,3], [3,4]], {origin: "A2"}); | ||||
| 		X.utils.sheet_add_aoa(ws, [[5,6,7], [6,7,8], [7,8,9]], {origin:{r:1, c:4}}); | ||||
| 		X.utils.sheet_add_aoa(ws, [[4,5,6,7,8,9,0]], {origin: -1}); | ||||
| 		assert.equal(X.utils.sheet_to_csv(ws).trim(), "S,h,e,e,t,J,S\n1,2,,,5,6,7\n2,3,,,6,7,8\n3,4,,,7,8,9\n4,5,6,7,8,9,0"); | ||||
| 	}); | ||||
| }); | ||||
| 
 | ||||
| function coreprop(props) { | ||||
|  | ||||
							
								
								
									
										24
									
								
								types/doc.ts
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										24
									
								
								types/doc.ts
									
									
									
									
									
								
							| @ -64,6 +64,11 @@ const ws1 = XLSX.utils.aoa_to_sheet([ | ||||
| 	sheetStubs: false | ||||
| }); | ||||
| 
 | ||||
| const ws1b = XLSX.utils.aoa_to_sheet([ "SheetJS".split("") ]); | ||||
| XLSX.utils.sheet_add_aoa(ws1b, [[1,2], [2,3], [3,4]], {origin: "A2"}); | ||||
| XLSX.utils.sheet_add_aoa(ws1b, [[5,6,7], [6,7,8], [7,8,9]], {origin:{r:1, c:4}}); | ||||
| XLSX.utils.sheet_add_aoa(ws1b, [[4,5,6,7,8,9,0]], {origin: -1}); | ||||
| 
 | ||||
| const ws2 = XLSX.utils.json_to_sheet([ | ||||
|     {S:1,h:2,e:3,e_1:4,t:5,J:6,S_1:7}, | ||||
|     {S:2,h:3,e:4,e_1:5,t:6,J:7,S_1:8} | ||||
| @ -73,6 +78,25 @@ const ws2 = XLSX.utils.json_to_sheet([ | ||||
| 	dateNF: "yyyy-mm-dd" | ||||
| }); | ||||
| 
 | ||||
| const ws2b = XLSX.utils.json_to_sheet([ | ||||
|   { A:"S", B:"h", C:"e", D:"e", E:"t", F:"J", G:"S" }, | ||||
|   { A: 1,  B: 2,  C: 3,  D: 4,  E: 5,  F: 6,  G: 7  }, | ||||
|   { A: 2,  B: 3,  C: 4,  D: 5,  E: 6,  F: 7,  G: 8  } | ||||
| ], {header:["A","B","C","D","E","F","G"], skipHeader:true}); | ||||
| 
 | ||||
| const ws2c = XLSX.utils.json_to_sheet([ | ||||
|   { A: "S", B: "h", C: "e", D: "e", E: "t", F: "J", G: "S" } | ||||
| ], {header: ["A", "B", "C", "D", "E", "F", "G"], skipHeader: true}); | ||||
| XLSX.utils.sheet_add_json(ws2c, [ | ||||
|   { A: 1, B: 2 }, { A: 2, B: 3 }, { A: 3, B: 4 } | ||||
| ], {skipHeader: true, origin: "A2"}); | ||||
| XLSX.utils.sheet_add_json(ws2c, [ | ||||
|   { A: 5, B: 6, C: 7 }, { A: 6, B: 7, C: 8 }, { A: 7, B: 8, C: 9 } | ||||
| ], {skipHeader: true, origin: { r: 1, c: 4 }, header: [ "A", "B", "C" ]}); | ||||
| XLSX.utils.sheet_add_json(ws2c, [ | ||||
|   { A: 4, B: 5, C: 6, D: 7, E: 8, F: 9, G: 0 } | ||||
| ], {header: ["A", "B", "C", "D", "E", "F", "G"], skipHeader: true, origin: -1}); | ||||
| 
 | ||||
| const tbl = {}; /* document.getElementById('table'); */ | ||||
| const ws3 = XLSX.utils.table_to_sheet(tbl, { | ||||
| 	raw: true, | ||||
|  | ||||
							
								
								
									
										21
									
								
								types/index.d.ts
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										21
									
								
								types/index.d.ts
									
									
									
									
										vendored
									
									
								
							| @ -596,6 +596,11 @@ export interface Sheet2CSVOpts extends DateNFOption { | ||||
|     skipHidden?: boolean; | ||||
| } | ||||
| 
 | ||||
| export interface OriginOption { | ||||
|     /** Top-Left cell for operation (CellAddress or A1 string or row) */ | ||||
|     origin?: number | string | CellAddress; | ||||
| } | ||||
| 
 | ||||
| export interface Sheet2HTMLOpts { | ||||
|     /** Add contenteditable to every cell */ | ||||
|     editable?: boolean; | ||||
| @ -632,11 +637,18 @@ export interface AOA2SheetOpts extends CommonOptions, DateNFOption { | ||||
|     sheetStubs?: boolean; | ||||
| } | ||||
| 
 | ||||
| export interface SheetAOAOpts extends AOA2SheetOpts, OriginOption {} | ||||
| 
 | ||||
| export interface JSON2SheetOpts extends CommonOptions, DateNFOption { | ||||
|     /** Use specified column order */ | ||||
|     header?: string[]; | ||||
| 
 | ||||
|     /** Skip header row in generated sheet */ | ||||
|     skipHeader?: boolean; | ||||
| } | ||||
| 
 | ||||
| export interface SheetJSONOpts extends JSON2SheetOpts, OriginOption {} | ||||
| 
 | ||||
| export interface Table2SheetOpts extends CommonOptions, DateNFOption { | ||||
|     /* If true, plaintext parsing will not parse values */ | ||||
|     raw?: boolean; | ||||
| @ -739,6 +751,15 @@ export interface XLSX$Utils { | ||||
|     /** Assign an Array Formula to a range */ | ||||
|     sheet_set_array_formula(ws: WorkSheet, range: Range|string, formula: string): WorkSheet; | ||||
| 
 | ||||
|     /** Add an array of arrays of JS data to a worksheet */ | ||||
|     sheet_add_aoa<T>(ws: WorkSheet, data: T[][], opts?: SheetAOAOpts): WorkSheet; | ||||
|     sheet_add_aoa(ws: WorkSheet, data: any[][], opts?: SheetAOAOpts): WorkSheet; | ||||
| 
 | ||||
|     /** Add an array of JS objects to a worksheet */ | ||||
|     sheet_add_json(ws: WorkSheet, data: any[], opts?: SheetJSONOpts): WorkSheet; | ||||
|     sheet_add_json<T>(ws: WorkSheet, data: T[], opts?: SheetJSONOpts): WorkSheet; | ||||
| 
 | ||||
| 
 | ||||
|     consts: XLSX$Consts; | ||||
| } | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										185
									
								
								xlsx.flow.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										185
									
								
								xlsx.flow.js
									
									
									
									
									
								
							| @ -4,7 +4,7 @@ | ||||
| /*global global, exports, module, require:false, process:false, Buffer:false */ | ||||
| var XLSX = {}; | ||||
| (function make_xlsx(XLSX){ | ||||
| XLSX.version = '0.11.16'; | ||||
| XLSX.version = '0.11.17'; | ||||
| var current_codepage = 1200, current_ansi = 1252; | ||||
| /*:: declare var cptable:any; */ | ||||
| /*global cptable:true */ | ||||
| @ -2118,11 +2118,16 @@ function escapexml(text/*:string*/, xml/*:?boolean*/)/*:string*/{ | ||||
| function escapexmltag(text/*:string*/)/*:string*/{ return escapexml(text).replace(/ /g,"_x0020_"); } | ||||
| 
 | ||||
| var htmlcharegex = /[\u0000-\u001f]/g; | ||||
| function escapehtml(text){ | ||||
| function escapehtml(text/*:string*/)/*:string*/{ | ||||
| 	var s = text + ''; | ||||
| 	return s.replace(decregex, function(y) { return rencoding[y]; }).replace(htmlcharegex,function(s) { return "&#x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + ";"; }); | ||||
| } | ||||
| 
 | ||||
| function escapexlml(text/*:string*/)/*:string*/{ | ||||
| 	var s = text + ''; | ||||
| 	return s.replace(decregex, function(y) { return rencoding[y]; }).replace(htmlcharegex,function(s) { return "&#x" + (s.charCodeAt(0).toString(16)).toUpperCase() + ";"; }); | ||||
| } | ||||
| 
 | ||||
| /* TODO: handle codepages */ | ||||
| var xlml_fixstr/*:StringConv*/ = (function() { | ||||
| 	var entregex = /&#(\d+);/g; | ||||
| @ -2615,8 +2620,8 @@ function shift_cell_xls(cell/*:CellAddress*/, tgt/*:any*/, opts/*:?any*/)/*:Cell | ||||
| 		if(out.cRel) out.c += tgt.s.c; | ||||
| 		if(out.rRel) out.r += tgt.s.r; | ||||
| 	} else { | ||||
| 		out.c += tgt.c; | ||||
| 		out.r += tgt.r; | ||||
| 		if(out.cRel) out.c += tgt.c; | ||||
| 		if(out.rRel) out.r += tgt.r; | ||||
| 	} | ||||
| 	if(!opts || opts.biff < 12) { | ||||
| 		while(out.c >= 0x100) out.c -= 0x100; | ||||
| @ -2772,20 +2777,38 @@ function sheet_to_workbook(sheet/*:Worksheet*/, opts)/*:Workbook*/ { | ||||
| 	return { SheetNames: [n], Sheets: sheets }; | ||||
| } | ||||
| 
 | ||||
| function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ { | ||||
| function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ { | ||||
| 	var o = opts || {}; | ||||
| 	if(DENSE != null && o.dense == null) o.dense = DENSE; | ||||
| 	var ws/*:Worksheet*/ = o.dense ? ([]/*:any*/) : ({}/*:any*/); | ||||
| 	var dense = _ws ? Array.isArray(_ws) : o.dense; | ||||
| 	if(DENSE != null && dense == null) dense = DENSE; | ||||
| 	var ws/*:Worksheet*/ = _ws || (dense ? ([]/*:any*/) : ({}/*:any*/)); | ||||
| 	var _R = 0, _C = 0; | ||||
| 	if(ws && o.origin != null) { | ||||
| 		if(typeof o.origin == 'number') _R = o.origin; | ||||
| 		else { | ||||
| 			var _origin/*:CellAddress*/ = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin; | ||||
| 			_R = _origin.r; _C = _origin.c; | ||||
| 		} | ||||
| 	} | ||||
| 	var range/*:Range*/ = ({s: {c:10000000, r:10000000}, e: {c:0, r:0}}/*:any*/); | ||||
| 	if(ws['!ref']) { | ||||
| 		var _range = safe_decode_range(ws['!ref']); | ||||
| 		range.s.c = _range.s.c; | ||||
| 		range.s.r = _range.s.r; | ||||
| 		range.e.c = Math.max(range.e.c, _range.e.c); | ||||
| 		range.e.r = Math.max(range.e.r, _range.e.r); | ||||
| 		if(_R == -1) range.e.r = _R = _range.e.r + 1; | ||||
| 	} | ||||
| 	for(var R = 0; R != data.length; ++R) { | ||||
| 		for(var C = 0; C != data[R].length; ++C) { | ||||
| 			if(typeof data[R][C] === 'undefined') continue; | ||||
| 			var cell/*:Cell*/ = ({v: data[R][C] }/*:any*/); | ||||
| 			if(Array.isArray(cell.v)) { cell.f = data[R][C][1]; cell.v = cell.v[0]; } | ||||
| 			if(range.s.r > R) range.s.r = R; | ||||
| 			if(range.s.c > C) range.s.c = C; | ||||
| 			if(range.e.r < R) range.e.r = R; | ||||
| 			if(range.e.c < C) range.e.c = C; | ||||
| 			var __R = _R + R, __C = _C + C; | ||||
| 			if(range.s.r > __R) range.s.r = __R; | ||||
| 			if(range.s.c > __C) range.s.c = __C; | ||||
| 			if(range.e.r < __R) range.e.r = __R; | ||||
| 			if(range.e.c < __C) range.e.c = __C; | ||||
| 			if(cell.v === null) { if(cell.f) cell.t = 'n'; else if(!o.cellStubs) continue; else cell.t = 'z'; } | ||||
| 			else if(typeof cell.v === 'number') cell.t = 'n'; | ||||
| 			else if(typeof cell.v === 'boolean') cell.t = 'b'; | ||||
| @ -2795,11 +2818,11 @@ function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ { | ||||
| 				else { cell.t = 'n'; cell.v = datenum(cell.v); cell.w = SSF.format(cell.z, cell.v); } | ||||
| 			} | ||||
| 			else cell.t = 's'; | ||||
| 			if(o.dense) { | ||||
| 				if(!ws[R]) ws[R] = []; | ||||
| 				ws[R][C] = cell; | ||||
| 			if(dense) { | ||||
| 				if(!ws[__R]) ws[__R] = []; | ||||
| 				ws[__R][__C] = cell; | ||||
| 			} else { | ||||
| 				var cell_ref = encode_cell(({c:C,r:R}/*:any*/)); | ||||
| 				var cell_ref = encode_cell(({c:__C,r:__R}/*:any*/)); | ||||
| 				ws[cell_ref] = cell; | ||||
| 			} | ||||
| 		} | ||||
| @ -2807,6 +2830,7 @@ function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ { | ||||
| 	if(range.s.c < 10000000) ws['!ref'] = encode_range(range); | ||||
| 	return ws; | ||||
| } | ||||
| function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ { return sheet_add_aoa(null, data, opts); } | ||||
| 
 | ||||
| function write_UInt32LE(x/*:number*/, o) { | ||||
| 	if(!o) o = new_buf(4); | ||||
| @ -4132,6 +4156,7 @@ function xlml_write_custprops(Props, Custprops, opts) { | ||||
| 	if(Custprops) keys(Custprops).forEach(function(k) { | ||||
| 		/*:: if(!Custprops) return; */ | ||||
| 		if(!Custprops.hasOwnProperty(k)) return; | ||||
| 		if(Props && Props.hasOwnProperty(k)) return; | ||||
| 		var m = Custprops[k]; | ||||
| 		var t = "string"; | ||||
| 		if(typeof m == 'number') { t = "float"; m = String(m); } | ||||
| @ -5309,7 +5334,7 @@ function parse_ShrFmla(blob, length, opts) { | ||||
| 	blob.l++; | ||||
| 	var cUse = blob.read_shift(1); | ||||
| 	length -= 8; | ||||
| 	return [parse_SharedParsedFormula(blob, length, opts), cUse]; | ||||
| 	return [parse_SharedParsedFormula(blob, length, opts), cUse, ref]; | ||||
| } | ||||
| 
 | ||||
| /* 2.4.4 TODO */ | ||||
| @ -7184,10 +7209,8 @@ function parse_DataSpaceDefinition(blob, length)/*:Array<string>*/ { | ||||
| function parse_TransformInfoHeader(blob, length) { | ||||
| 	var o = {}; | ||||
| 	var len = blob.read_shift(4); | ||||
| 	var tgt = blob.l + len - 4; | ||||
| 	blob.l += 4; // must be 0x1
 | ||||
| 	o.id = blob.read_shift(0, 'lpp4'); | ||||
| 	if(tgt != blob.l) throw new Error("Bad TransformInfoHeader record: " + blob.l + " != " + tgt); | ||||
| 	o.name = blob.read_shift(0, 'lpp4'); | ||||
| 	o.R = parse_CRYPTOVersion(blob, 4); | ||||
| 	o.U = parse_CRYPTOVersion(blob, 4); | ||||
| @ -9176,12 +9199,13 @@ var rc_to_a1 = (function(){ | ||||
| 
 | ||||
| var crefregex = /(^|[^._A-Z0-9])([$]?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])([$]?)([1-9]\d{0,5}|10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6])(?![_.\(A-Za-z0-9])/g; | ||||
| var a1_to_rc =(function(){ | ||||
| 	return function a1_to_rc(fstr, base) { | ||||
| 	return function a1_to_rc(fstr/*:string*/, base/*:CellAddress*/) { | ||||
| 		return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5, off, str) { | ||||
| 			/* TODO: handle fixcol / fixrow */ | ||||
| 			var c = decode_col($3) - base.c; | ||||
| 			var r = decode_row($5) - base.r; | ||||
| 			return $1 + "R" + (r == 0 ? "" : "[" + r + "]") + "C" + (c == 0 ? "" : "[" + c + "]"); | ||||
| 			var c = decode_col($3) - ($2 ? 0 : base.c); | ||||
| 			var r = decode_row($5) - ($4 ? 0 : base.r); | ||||
| 			var R = (r == 0 ? "" : !$4 ? "[" + r + "]" : (r+1)); | ||||
| 			var C = (c == 0 ? "" : !$2 ? "[" + c + "]" : (c+1)); | ||||
| 			return $1 + "R" + R + "C" + C; | ||||
| 		}); | ||||
| 	}; | ||||
| })(); | ||||
| @ -9277,7 +9301,7 @@ function parse_RgceLocRel(blob, length, opts) { | ||||
| 	if(biff >= 2 && biff <= 5) return parse_RgceLocRel_BIFF2(blob, length, opts); | ||||
| 	var r = blob.read_shift(biff >= 12 ? 4 : 2); | ||||
| 	var cl = blob.read_shift(2); | ||||
| 	var cRel = (cl & 0x8000) >> 15, rRel = (cl & 0x4000) >> 14; | ||||
| 	var cRel = (cl & 0x4000) >> 14, rRel = (cl & 0x8000) >> 15; | ||||
| 	cl &= 0x3FFF; | ||||
| 	if(rRel == 1) while(r > 0x7FFFF) r -= 0x100000; | ||||
| 	if(cRel == 1) while(cl > 0x1FFF) cl = cl - 0x4000; | ||||
| @ -10050,7 +10074,7 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks, | ||||
| 			case 'PtgErr': /* 2.5.198.57 */ | ||||
| 				stack.push(/*::String(*/f[1]/*::)*/); break; | ||||
| 			case 'PtgAreaN': /* 2.5.198.31 TODO */ | ||||
| 				type = f[1][0]; r = shift_range_xls(f[1][1], _range, opts); | ||||
| 				type = f[1][0]; r = shift_range_xls(f[1][1], cell ? {s:cell} : _range, opts); | ||||
| 				stack.push(encode_range_xls((r/*:any*/), opts)); | ||||
| 				break; | ||||
| 			case 'PtgArea': /* 2.5.198.27 TODO: fixed points */ | ||||
| @ -14359,7 +14383,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ { | ||||
| 			var _NamedRange = parsexmltag(Rn[0]); | ||||
| 			var _DefinedName/*:DefinedName*/ = ({ | ||||
| 				Name: _NamedRange.Name, | ||||
| 				Ref: rc_to_a1(_NamedRange.RefersTo.substr(1)) | ||||
| 				Ref: rc_to_a1(_NamedRange.RefersTo.substr(1), {r:0, c:0}) | ||||
| 			}/*:any*/); | ||||
| 			if(Workbook.Sheets.length>0) _DefinedName.Sheet=Workbook.Sheets.length-1; | ||||
| 			/*:: if(Workbook.Names) */Workbook.Names.push(_DefinedName); | ||||
| @ -14889,6 +14913,37 @@ function write_sty_xlml(wb, opts)/*:string*/ { | ||||
| 	}); | ||||
| 	return writextag("Styles", styles.join("")); | ||||
| } | ||||
| function write_name_xlml(n) { return writextag("NamedRange", null, {"ss:Name": n.Name, "ss:RefersTo":"=" + a1_to_rc(n.Ref, {r:0,c:0})}); } | ||||
| function write_names_xlml(wb, opts)/*:string*/ { | ||||
| 	if(!((wb||{}).Workbook||{}).Names) return ""; | ||||
| 	/*:: if(!wb || !wb.Workbook || !wb.Workbook.Names) throw new Error("unreachable"); */ | ||||
| 	var names/*:Array<any>*/ = wb.Workbook.Names; | ||||
| 	var out/*:Array<string>*/ = []; | ||||
| 	for(var i = 0; i < names.length; ++i) { | ||||
| 		var n = names[i]; | ||||
| 		if(n.Sheet != null) continue; | ||||
| 		if(n.Name.match(/^_xlfn\./)) continue; | ||||
| 		out.push(write_name_xlml(n)); | ||||
| 	} | ||||
| 	return writextag("Names", out.join("")); | ||||
| } | ||||
| function write_ws_xlml_names(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/)/*:string*/ { | ||||
| 	if(!ws) return ""; | ||||
| 	if(!((wb||{}).Workbook||{}).Names) return ""; | ||||
| 	/*:: if(!wb || !wb.Workbook || !wb.Workbook.Names) throw new Error("unreachable"); */ | ||||
| 	var names/*:Array<any>*/ = wb.Workbook.Names; | ||||
| 	var out/*:Array<string>*/ = []; | ||||
| 	outer: for(var i = 0; i < names.length; ++i) { | ||||
| 		var n = names[i]; | ||||
| 		if(n.Sheet != idx) continue; | ||||
| 		/*switch(n.Name) { | ||||
| 			case "_": continue; | ||||
| 		}*/ | ||||
| 		if(n.Name.match(/^_xlfn\./)) continue; | ||||
| 		out.push(write_name_xlml(n)); | ||||
| 	} | ||||
| 	return out.join(""); | ||||
| } | ||||
| /* WorksheetOptions */ | ||||
| function write_ws_xlml_wsopts(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/)/*:string*/ { | ||||
| 	if(!ws) return ""; | ||||
| @ -15007,7 +15062,7 @@ function write_ws_xlml_comment(comments/*:Array<any>*/)/*:string*/ { | ||||
| 	}).join(""); | ||||
| } | ||||
| function write_ws_xlml_cell(cell, ref/*:string*/, ws, opts, idx/*:number*/, wb, addr)/*:string*/{ | ||||
| 	if(!cell || cell.v == undefined && cell.f == undefined) return "<Cell></Cell>"; | ||||
| 	if(!cell || cell.v == undefined && cell.f == undefined) return ""; | ||||
| 
 | ||||
| 	var attr = {}; | ||||
| 	if(cell.f) attr["ss:Formula"] = "=" + escapexml(a1_to_rc(cell.f, addr)); | ||||
| @ -15037,11 +15092,12 @@ function write_ws_xlml_cell(cell, ref/*:string*/, ws, opts, idx/*:number*/, wb, | ||||
| 		case 'b': t = 'Boolean'; p = (cell.v ? "1" : "0"); break; | ||||
| 		case 'e': t = 'Error'; p = BErr[cell.v]; break; | ||||
| 		case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); if(cell.z == null) cell.z = cell.z || SSF._table[14]; break; | ||||
| 		case 's': t = 'String'; p = escapexml(cell.v||""); break; | ||||
| 		case 's': t = 'String'; p = escapexlml(cell.v||""); break; | ||||
| 	} | ||||
| 	/* TODO: cell style */ | ||||
| 	var os = get_cell_style(opts.cellXfs, cell, opts); | ||||
| 	attr["ss:StyleID"] = "s" + (21+os); | ||||
| 	attr["ss:Index"] = addr.c + 1; | ||||
| 	var _v = (cell.v != null ? p : ""); | ||||
| 	var m = '<Data ss:Type="' + t + '">' + _v + '</Data>'; | ||||
| 
 | ||||
| @ -15101,8 +15157,11 @@ function write_ws_xlml(idx/*:number*/, opts, wb/*:Workbook*/)/*:string*/ { | ||||
| 	var s = wb.SheetNames[idx]; | ||||
| 	var ws = wb.Sheets[s]; | ||||
| 
 | ||||
| 	var t/*:string*/ = ws ? write_ws_xlml_names(ws, opts, idx, wb) : ""; | ||||
| 	if(t.length > 0) o.push("<Names>" + t + "</Names>"); | ||||
| 
 | ||||
| 	/* Table */ | ||||
| 	var t = ws ? write_ws_xlml_table(ws, opts, idx, wb) : ""; | ||||
| 	t = ws ? write_ws_xlml_table(ws, opts, idx, wb) : ""; | ||||
| 	if(t.length > 0) o.push("<Table>" + t + "</Table>"); | ||||
| 
 | ||||
| 	/* WorksheetOptions */ | ||||
| @ -15125,9 +15184,11 @@ function write_xlml(wb, opts)/*:string*/ { | ||||
| 	d.push(write_props_xlml(wb, opts)); | ||||
| 	d.push(write_wb_xlml(wb, opts)); | ||||
| 	d.push(""); | ||||
| 	d.push(""); | ||||
| 	for(var i = 0; i < wb.SheetNames.length; ++i) | ||||
| 		d.push(writextag("Worksheet", write_ws_xlml(i, opts, wb), {"ss:Name":escapexml(wb.SheetNames[i])})); | ||||
| 	d[2] = write_sty_xlml(wb, opts); | ||||
| 	d[3] = write_names_xlml(wb, opts); | ||||
| 	return XML_HEADER + writextag("Workbook", d.join(""), { | ||||
| 		'xmlns':      XLMLNS.ss, | ||||
| 		'xmlns:o':    XLMLNS.o, | ||||
| @ -15244,7 +15305,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 	var cur_sheet = ""; | ||||
| 	var Preamble = {}; | ||||
| 	var lastcell, last_cell = "", cc, cmnt, rngC, rngR; | ||||
| 	var shared_formulae = {}; | ||||
| 	var sharedf = {}; | ||||
| 	var arrayf/*:Array<[Range, string]>*/ = []; | ||||
| 	var temp_val/*:Cell*/; | ||||
| 	var country; | ||||
| @ -15283,13 +15344,10 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 		} | ||||
| 		if(options.cellFormula && line.f) { | ||||
| 			for(var afi = 0; afi < arrayf.length; ++afi) { | ||||
| 				if(arrayf[afi][0].s.c > cell.c) continue; | ||||
| 				if(arrayf[afi][0].s.r > cell.r) continue; | ||||
| 				if(arrayf[afi][0].e.c < cell.c) continue; | ||||
| 				if(arrayf[afi][0].e.r < cell.r) continue; | ||||
| 				if(arrayf[afi][0].s.c > cell.c || arrayf[afi][0].s.r > cell.r) continue; | ||||
| 				if(arrayf[afi][0].e.c < cell.c || arrayf[afi][0].e.r < cell.r) continue; | ||||
| 				line.F = encode_range(arrayf[afi][0]); | ||||
| 				if(arrayf[afi][0].s.c != cell.c) delete line.f; | ||||
| 				if(arrayf[afi][0].s.r != cell.r) delete line.f; | ||||
| 				if(arrayf[afi][0].s.c != cell.c || arrayf[afi][0].s.r != cell.r) delete line.f; | ||||
| 				if(line.f) line.f = "" + stringify_formula(arrayf[afi][1], range, cell, supbooks, opts); | ||||
| 				break; | ||||
| 			} | ||||
| @ -15306,7 +15364,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 		enc: false, // encrypted
 | ||||
| 		sbcch: 0, // cch in the preceding SupBook
 | ||||
| 		snames: [], // sheetnames
 | ||||
| 		sharedf: shared_formulae, // shared formulae by address
 | ||||
| 		sharedf: sharedf, // shared formulae by address
 | ||||
| 		arrayf: arrayf, // array formulae array
 | ||||
| 		rrtabid: [], // RRTabId
 | ||||
| 		lastuser: "", // Last User from WriteAccess
 | ||||
| @ -15362,6 +15420,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 			if(R.n === 'EOF') val = R.f(blob, length, opts); | ||||
| 			else val = slurp(R, blob, length, opts); | ||||
| 			var Rn = R.n; | ||||
| 			if(file_depth == 0 && Rn != 'BOF') continue; | ||||
| 			/* nested switch statements to workaround V8 128 limit */ | ||||
| 			switch(Rn) { | ||||
| 				/* Workbook Options */ | ||||
| @ -15392,16 +15451,17 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 				case 'RRTabId': opts.rrtabid = val; break; | ||||
| 				case 'WinProtect': opts.winlocked = val; break; | ||||
| 				case 'Template': break; // TODO
 | ||||
| 				case 'RefreshAll': wb.opts.RefreshAll = val; break; | ||||
| 				case 'BookBool': break; // TODO
 | ||||
| 				case 'UsesELFs': break; | ||||
| 				case 'MTRSettings': break; | ||||
| 				case 'CalcCount': wb.opts.CalcCount = val; break; | ||||
| 				case 'CalcDelta': wb.opts.CalcDelta = val; break; | ||||
| 				case 'CalcIter': wb.opts.CalcIter = val; break; | ||||
| 				case 'CalcMode': wb.opts.CalcMode = val; break; | ||||
| 				case 'CalcPrecision': wb.opts.CalcPrecision = val; break; | ||||
| 				case 'CalcSaveRecalc': wb.opts.CalcSaveRecalc = val; break; | ||||
| 				case 'RefreshAll': | ||||
| 				case 'CalcCount': | ||||
| 				case 'CalcDelta': | ||||
| 				case 'CalcIter': | ||||
| 				case 'CalcMode': | ||||
| 				case 'CalcPrecision': | ||||
| 				case 'CalcSaveRecalc': | ||||
| 					wb.opts[Rn] = val; break; | ||||
| 				case 'CalcRefMode': opts.CalcRefMode = val; break; // TODO: implement R1C1
 | ||||
| 				case 'Uncalced': break; | ||||
| 				case 'ForceFullCalculation': wb.opts.FullCalc = val; break; | ||||
| @ -15543,7 +15603,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 						if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') { | ||||
| 							var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1]; | ||||
| 							var _fe = encode_cell({r:_fr, c:_fc}); | ||||
| 							if(shared_formulae[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); | ||||
| 							if(sharedf[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); | ||||
| 							else temp_val.F = ((options.dense ? (out[_fr]||[])[_fc]: out[_fe]) || {}).F; | ||||
| 						} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); | ||||
| 					} | ||||
| @ -15583,7 +15643,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 					if(last_cell) { | ||||
| 						/* TODO: capture range */ | ||||
| 						if(!last_formula) break; /* technically unreachable */ | ||||
| 						shared_formulae[encode_cell(last_formula.cell)]= val[0]; | ||||
| 						sharedf[encode_cell(last_formula.cell)]= val[0]; | ||||
| 						cc = options.dense ? (out[last_formula.cell.r]||[])[last_formula.cell.c] : out[encode_cell(last_formula.cell)]; | ||||
| 						(cc||{}).f = ""+stringify_formula(val[0], range, lastcell, supbooks, opts); | ||||
| 					} | ||||
| @ -19325,14 +19385,29 @@ function sheet_to_formulae(sheet/*:Worksheet*/)/*:Array<string>*/ { | ||||
| 	return cmds; | ||||
| } | ||||
| 
 | ||||
| function json_to_sheet(js/*:Array<any>*/, opts)/*:Worksheet*/ { | ||||
| function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet*/ { | ||||
| 	var o = opts || {}; | ||||
| 	var ws = ({}/*:any*/); | ||||
| 	var offset = +!o.skipHeader; | ||||
| 	var ws/*:Worksheet*/ = _ws || ({}/*:any*/); | ||||
| 	var _R = 0, _C = 0; | ||||
| 	if(ws && o.origin != null) { | ||||
| 		if(typeof o.origin == 'number') _R = o.origin; | ||||
| 		else { | ||||
| 			var _origin/*:CellAddress*/ = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin; | ||||
| 			_R = _origin.r; _C = _origin.c; | ||||
| 		} | ||||
| 	} | ||||
| 	var cell/*:Cell*/; | ||||
| 	var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:0, r:js.length}}/*:any*/); | ||||
| 	var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:_C, r:_R + js.length - 1 + offset}}/*:any*/); | ||||
| 	if(ws['!ref']) { | ||||
| 		var _range = safe_decode_range(ws['!ref']); | ||||
| 		range.e.c = Math.max(range.e.c, _range.e.c); | ||||
| 		range.e.r = Math.max(range.e.r, _range.e.r); | ||||
| 		if(_R == -1) { _R = range.e.r + 1; range.e.r = _R + js.length - 1 + offset; } | ||||
| 	} | ||||
| 	var hdr/*:Array<string>*/ = o.header || [], C = 0; | ||||
| 
 | ||||
| 	js.forEach(function (JS, R) { | ||||
| 	js.forEach(function (JS, R/*:number*/) { | ||||
| 		keys(JS).filter(function(x) { return JS.hasOwnProperty(x); }).forEach(function(k) { | ||||
| 			if((C=hdr.indexOf(k)) == -1) hdr[C=hdr.length] = k; | ||||
| 			var v = JS[k]; | ||||
| @ -19346,15 +19421,17 @@ function json_to_sheet(js/*:Array<any>*/, opts)/*:Worksheet*/ { | ||||
| 				if(!o.cellDates) { t = 'n'; v = datenum(v); } | ||||
| 				z = o.dateNF || SSF._table[14]; | ||||
| 			} | ||||
| 			ws[encode_cell({c:C,r:R+1})] = cell = ({t:t, v:v}/*:any*/); | ||||
| 			ws[encode_cell({c:_C + C,r:_R + R + offset})] = cell = ({t:t, v:v}/*:any*/); | ||||
| 			if(z) cell.z = z; | ||||
| 		}); | ||||
| 	}); | ||||
| 	range.e.c = hdr.length - 1; | ||||
| 	for(C = 0; C < hdr.length; ++C) ws[encode_col(C) + "1"] = {t:'s', v:hdr[C]}; | ||||
| 	range.e.c = Math.max(range.e.c, _C + hdr.length - 1); | ||||
| 	var __R = encode_row(_R); | ||||
| 	if(offset) for(C = 0; C < hdr.length; ++C) ws[encode_col(C + _C) + __R] = {t:'s', v:hdr[C]}; | ||||
| 	ws['!ref'] = encode_range(range); | ||||
| 	return ws; | ||||
| } | ||||
| function json_to_sheet(js/*:Array<any>*/, opts)/*:Worksheet*/ { return sheet_add_json(null, js, opts); } | ||||
| 
 | ||||
| var utils/*:any*/ = { | ||||
| 	encode_col: encode_col, | ||||
| @ -19371,6 +19448,8 @@ var utils/*:any*/ = { | ||||
| 	make_csv: sheet_to_csv, | ||||
| 	make_json: sheet_to_json, | ||||
| 	make_formulae: sheet_to_formulae, | ||||
| 	sheet_add_aoa: sheet_add_aoa, | ||||
| 	sheet_add_json: sheet_add_json, | ||||
| 	aoa_to_sheet: aoa_to_sheet, | ||||
| 	json_to_sheet: json_to_sheet, | ||||
| 	table_to_sheet: parse_dom_table, | ||||
|  | ||||
							
								
								
									
										177
									
								
								xlsx.js
									
									
									
										generated
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										177
									
								
								xlsx.js
									
									
									
										generated
									
									
									
								
							| @ -4,7 +4,7 @@ | ||||
| /*global global, exports, module, require:false, process:false, Buffer:false */ | ||||
| var XLSX = {}; | ||||
| (function make_xlsx(XLSX){ | ||||
| XLSX.version = '0.11.16'; | ||||
| XLSX.version = '0.11.17'; | ||||
| var current_codepage = 1200, current_ansi = 1252; | ||||
| /*global cptable:true */ | ||||
| if(typeof module !== "undefined" && typeof require !== 'undefined') { | ||||
| @ -2051,6 +2051,11 @@ function escapehtml(text){ | ||||
| 	return s.replace(decregex, function(y) { return rencoding[y]; }).replace(htmlcharegex,function(s) { return "&#x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + ";"; }); | ||||
| } | ||||
| 
 | ||||
| function escapexlml(text){ | ||||
| 	var s = text + ''; | ||||
| 	return s.replace(decregex, function(y) { return rencoding[y]; }).replace(htmlcharegex,function(s) { return "&#x" + (s.charCodeAt(0).toString(16)).toUpperCase() + ";"; }); | ||||
| } | ||||
| 
 | ||||
| /* TODO: handle codepages */ | ||||
| var xlml_fixstr = (function() { | ||||
| 	var entregex = /&#(\d+);/g; | ||||
| @ -2538,8 +2543,8 @@ function shift_cell_xls(cell, tgt, opts) { | ||||
| 		if(out.cRel) out.c += tgt.s.c; | ||||
| 		if(out.rRel) out.r += tgt.s.r; | ||||
| 	} else { | ||||
| 		out.c += tgt.c; | ||||
| 		out.r += tgt.r; | ||||
| 		if(out.cRel) out.c += tgt.c; | ||||
| 		if(out.rRel) out.r += tgt.r; | ||||
| 	} | ||||
| 	if(!opts || opts.biff < 12) { | ||||
| 		while(out.c >= 0x100) out.c -= 0x100; | ||||
| @ -2689,20 +2694,38 @@ function sheet_to_workbook(sheet, opts) { | ||||
| 	return { SheetNames: [n], Sheets: sheets }; | ||||
| } | ||||
| 
 | ||||
| function aoa_to_sheet(data, opts) { | ||||
| function sheet_add_aoa(_ws, data, opts) { | ||||
| 	var o = opts || {}; | ||||
| 	if(DENSE != null && o.dense == null) o.dense = DENSE; | ||||
| 	var ws = o.dense ? ([]) : ({}); | ||||
| 	var dense = _ws ? Array.isArray(_ws) : o.dense; | ||||
| 	if(DENSE != null && dense == null) dense = DENSE; | ||||
| 	var ws = _ws || (dense ? ([]) : ({})); | ||||
| 	var _R = 0, _C = 0; | ||||
| 	if(ws && o.origin != null) { | ||||
| 		if(typeof o.origin == 'number') _R = o.origin; | ||||
| 		else { | ||||
| 			var _origin = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin; | ||||
| 			_R = _origin.r; _C = _origin.c; | ||||
| 		} | ||||
| 	} | ||||
| 	var range = ({s: {c:10000000, r:10000000}, e: {c:0, r:0}}); | ||||
| 	if(ws['!ref']) { | ||||
| 		var _range = safe_decode_range(ws['!ref']); | ||||
| 		range.s.c = _range.s.c; | ||||
| 		range.s.r = _range.s.r; | ||||
| 		range.e.c = Math.max(range.e.c, _range.e.c); | ||||
| 		range.e.r = Math.max(range.e.r, _range.e.r); | ||||
| 		if(_R == -1) range.e.r = _R = _range.e.r + 1; | ||||
| 	} | ||||
| 	for(var R = 0; R != data.length; ++R) { | ||||
| 		for(var C = 0; C != data[R].length; ++C) { | ||||
| 			if(typeof data[R][C] === 'undefined') continue; | ||||
| 			var cell = ({v: data[R][C] }); | ||||
| 			if(Array.isArray(cell.v)) { cell.f = data[R][C][1]; cell.v = cell.v[0]; } | ||||
| 			if(range.s.r > R) range.s.r = R; | ||||
| 			if(range.s.c > C) range.s.c = C; | ||||
| 			if(range.e.r < R) range.e.r = R; | ||||
| 			if(range.e.c < C) range.e.c = C; | ||||
| 			var __R = _R + R, __C = _C + C; | ||||
| 			if(range.s.r > __R) range.s.r = __R; | ||||
| 			if(range.s.c > __C) range.s.c = __C; | ||||
| 			if(range.e.r < __R) range.e.r = __R; | ||||
| 			if(range.e.c < __C) range.e.c = __C; | ||||
| 			if(cell.v === null) { if(cell.f) cell.t = 'n'; else if(!o.cellStubs) continue; else cell.t = 'z'; } | ||||
| 			else if(typeof cell.v === 'number') cell.t = 'n'; | ||||
| 			else if(typeof cell.v === 'boolean') cell.t = 'b'; | ||||
| @ -2712,11 +2735,11 @@ function aoa_to_sheet(data, opts) { | ||||
| 				else { cell.t = 'n'; cell.v = datenum(cell.v); cell.w = SSF.format(cell.z, cell.v); } | ||||
| 			} | ||||
| 			else cell.t = 's'; | ||||
| 			if(o.dense) { | ||||
| 				if(!ws[R]) ws[R] = []; | ||||
| 				ws[R][C] = cell; | ||||
| 			if(dense) { | ||||
| 				if(!ws[__R]) ws[__R] = []; | ||||
| 				ws[__R][__C] = cell; | ||||
| 			} else { | ||||
| 				var cell_ref = encode_cell(({c:C,r:R})); | ||||
| 				var cell_ref = encode_cell(({c:__C,r:__R})); | ||||
| 				ws[cell_ref] = cell; | ||||
| 			} | ||||
| 		} | ||||
| @ -2724,6 +2747,7 @@ function aoa_to_sheet(data, opts) { | ||||
| 	if(range.s.c < 10000000) ws['!ref'] = encode_range(range); | ||||
| 	return ws; | ||||
| } | ||||
| function aoa_to_sheet(data, opts) { return sheet_add_aoa(null, data, opts); } | ||||
| 
 | ||||
| function write_UInt32LE(x, o) { | ||||
| 	if(!o) o = new_buf(4); | ||||
| @ -4047,6 +4071,7 @@ if(!Props.hasOwnProperty(k)) return; | ||||
| 	}); | ||||
| 	if(Custprops) keys(Custprops).forEach(function(k) { | ||||
| if(!Custprops.hasOwnProperty(k)) return; | ||||
| 		if(Props && Props.hasOwnProperty(k)) return; | ||||
| 		var m = Custprops[k]; | ||||
| 		var t = "string"; | ||||
| 		if(typeof m == 'number') { t = "float"; m = String(m); } | ||||
| @ -5224,7 +5249,7 @@ function parse_ShrFmla(blob, length, opts) { | ||||
| 	blob.l++; | ||||
| 	var cUse = blob.read_shift(1); | ||||
| 	length -= 8; | ||||
| 	return [parse_SharedParsedFormula(blob, length, opts), cUse]; | ||||
| 	return [parse_SharedParsedFormula(blob, length, opts), cUse, ref]; | ||||
| } | ||||
| 
 | ||||
| /* 2.4.4 TODO */ | ||||
| @ -7097,10 +7122,8 @@ function parse_DataSpaceDefinition(blob, length) { | ||||
| function parse_TransformInfoHeader(blob, length) { | ||||
| 	var o = {}; | ||||
| 	var len = blob.read_shift(4); | ||||
| 	var tgt = blob.l + len - 4; | ||||
| 	blob.l += 4; // must be 0x1
 | ||||
| 	o.id = blob.read_shift(0, 'lpp4'); | ||||
| 	if(tgt != blob.l) throw new Error("Bad TransformInfoHeader record: " + blob.l + " != " + tgt); | ||||
| 	o.name = blob.read_shift(0, 'lpp4'); | ||||
| 	o.R = parse_CRYPTOVersion(blob, 4); | ||||
| 	o.U = parse_CRYPTOVersion(blob, 4); | ||||
| @ -9089,10 +9112,11 @@ var crefregex = /(^|[^._A-Z0-9])([$]?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A | ||||
| var a1_to_rc =(function(){ | ||||
| 	return function a1_to_rc(fstr, base) { | ||||
| 		return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5, off, str) { | ||||
| 			/* TODO: handle fixcol / fixrow */ | ||||
| 			var c = decode_col($3) - base.c; | ||||
| 			var r = decode_row($5) - base.r; | ||||
| 			return $1 + "R" + (r == 0 ? "" : "[" + r + "]") + "C" + (c == 0 ? "" : "[" + c + "]"); | ||||
| 			var c = decode_col($3) - ($2 ? 0 : base.c); | ||||
| 			var r = decode_row($5) - ($4 ? 0 : base.r); | ||||
| 			var R = (r == 0 ? "" : !$4 ? "[" + r + "]" : (r+1)); | ||||
| 			var C = (c == 0 ? "" : !$2 ? "[" + c + "]" : (c+1)); | ||||
| 			return $1 + "R" + R + "C" + C; | ||||
| 		}); | ||||
| 	}; | ||||
| })(); | ||||
| @ -9188,7 +9212,7 @@ function parse_RgceLocRel(blob, length, opts) { | ||||
| 	if(biff >= 2 && biff <= 5) return parse_RgceLocRel_BIFF2(blob, length, opts); | ||||
| 	var r = blob.read_shift(biff >= 12 ? 4 : 2); | ||||
| 	var cl = blob.read_shift(2); | ||||
| 	var cRel = (cl & 0x8000) >> 15, rRel = (cl & 0x4000) >> 14; | ||||
| 	var cRel = (cl & 0x4000) >> 14, rRel = (cl & 0x8000) >> 15; | ||||
| 	cl &= 0x3FFF; | ||||
| 	if(rRel == 1) while(r > 0x7FFFF) r -= 0x100000; | ||||
| 	if(cRel == 1) while(cl > 0x1FFF) cl = cl - 0x4000; | ||||
| @ -9960,7 +9984,7 @@ function stringify_formula(formula/*Array<any>*/, range, cell, supbooks, opts) { | ||||
| 			case 'PtgErr': /* 2.5.198.57 */ | ||||
| 				stack.push(f[1]); break; | ||||
| 			case 'PtgAreaN': /* 2.5.198.31 TODO */ | ||||
| 				type = f[1][0]; r = shift_range_xls(f[1][1], _range, opts); | ||||
| 				type = f[1][0]; r = shift_range_xls(f[1][1], cell ? {s:cell} : _range, opts); | ||||
| 				stack.push(encode_range_xls((r), opts)); | ||||
| 				break; | ||||
| 			case 'PtgArea': /* 2.5.198.27 TODO: fixed points */ | ||||
| @ -14263,7 +14287,7 @@ for(var cma = c; cma <= cc; ++cma) { | ||||
| 			var _NamedRange = parsexmltag(Rn[0]); | ||||
| 			var _DefinedName = ({ | ||||
| 				Name: _NamedRange.Name, | ||||
| 				Ref: rc_to_a1(_NamedRange.RefersTo.substr(1)) | ||||
| 				Ref: rc_to_a1(_NamedRange.RefersTo.substr(1), {r:0, c:0}) | ||||
| 			}); | ||||
| 			if(Workbook.Sheets.length>0) _DefinedName.Sheet=Workbook.Sheets.length-1; | ||||
| Workbook.Names.push(_DefinedName); | ||||
| @ -14791,6 +14815,35 @@ function write_sty_xlml(wb, opts) { | ||||
| 	}); | ||||
| 	return writextag("Styles", styles.join("")); | ||||
| } | ||||
| function write_name_xlml(n) { return writextag("NamedRange", null, {"ss:Name": n.Name, "ss:RefersTo":"=" + a1_to_rc(n.Ref, {r:0,c:0})}); } | ||||
| function write_names_xlml(wb, opts) { | ||||
| 	if(!((wb||{}).Workbook||{}).Names) return ""; | ||||
| var names = wb.Workbook.Names; | ||||
| 	var out = []; | ||||
| 	for(var i = 0; i < names.length; ++i) { | ||||
| 		var n = names[i]; | ||||
| 		if(n.Sheet != null) continue; | ||||
| 		if(n.Name.match(/^_xlfn\./)) continue; | ||||
| 		out.push(write_name_xlml(n)); | ||||
| 	} | ||||
| 	return writextag("Names", out.join("")); | ||||
| } | ||||
| function write_ws_xlml_names(ws, opts, idx, wb) { | ||||
| 	if(!ws) return ""; | ||||
| 	if(!((wb||{}).Workbook||{}).Names) return ""; | ||||
| var names = wb.Workbook.Names; | ||||
| 	var out = []; | ||||
| 	outer: for(var i = 0; i < names.length; ++i) { | ||||
| 		var n = names[i]; | ||||
| 		if(n.Sheet != idx) continue; | ||||
| 		/*switch(n.Name) { | ||||
| 			case "_": continue; | ||||
| 		}*/ | ||||
| 		if(n.Name.match(/^_xlfn\./)) continue; | ||||
| 		out.push(write_name_xlml(n)); | ||||
| 	} | ||||
| 	return out.join(""); | ||||
| } | ||||
| /* WorksheetOptions */ | ||||
| function write_ws_xlml_wsopts(ws, opts, idx, wb) { | ||||
| 	if(!ws) return ""; | ||||
| @ -14909,7 +14962,7 @@ function write_ws_xlml_comment(comments) { | ||||
| 	}).join(""); | ||||
| } | ||||
| function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr){ | ||||
| 	if(!cell || cell.v == undefined && cell.f == undefined) return "<Cell></Cell>"; | ||||
| 	if(!cell || cell.v == undefined && cell.f == undefined) return ""; | ||||
| 
 | ||||
| 	var attr = {}; | ||||
| 	if(cell.f) attr["ss:Formula"] = "=" + escapexml(a1_to_rc(cell.f, addr)); | ||||
| @ -14939,11 +14992,12 @@ function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr){ | ||||
| 		case 'b': t = 'Boolean'; p = (cell.v ? "1" : "0"); break; | ||||
| 		case 'e': t = 'Error'; p = BErr[cell.v]; break; | ||||
| 		case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); if(cell.z == null) cell.z = cell.z || SSF._table[14]; break; | ||||
| 		case 's': t = 'String'; p = escapexml(cell.v||""); break; | ||||
| 		case 's': t = 'String'; p = escapexlml(cell.v||""); break; | ||||
| 	} | ||||
| 	/* TODO: cell style */ | ||||
| 	var os = get_cell_style(opts.cellXfs, cell, opts); | ||||
| 	attr["ss:StyleID"] = "s" + (21+os); | ||||
| 	attr["ss:Index"] = addr.c + 1; | ||||
| 	var _v = (cell.v != null ? p : ""); | ||||
| 	var m = '<Data ss:Type="' + t + '">' + _v + '</Data>'; | ||||
| 
 | ||||
| @ -15003,8 +15057,11 @@ function write_ws_xlml(idx, opts, wb) { | ||||
| 	var s = wb.SheetNames[idx]; | ||||
| 	var ws = wb.Sheets[s]; | ||||
| 
 | ||||
| 	var t = ws ? write_ws_xlml_names(ws, opts, idx, wb) : ""; | ||||
| 	if(t.length > 0) o.push("<Names>" + t + "</Names>"); | ||||
| 
 | ||||
| 	/* Table */ | ||||
| 	var t = ws ? write_ws_xlml_table(ws, opts, idx, wb) : ""; | ||||
| 	t = ws ? write_ws_xlml_table(ws, opts, idx, wb) : ""; | ||||
| 	if(t.length > 0) o.push("<Table>" + t + "</Table>"); | ||||
| 
 | ||||
| 	/* WorksheetOptions */ | ||||
| @ -15027,9 +15084,11 @@ function write_xlml(wb, opts) { | ||||
| 	d.push(write_props_xlml(wb, opts)); | ||||
| 	d.push(write_wb_xlml(wb, opts)); | ||||
| 	d.push(""); | ||||
| 	d.push(""); | ||||
| 	for(var i = 0; i < wb.SheetNames.length; ++i) | ||||
| 		d.push(writextag("Worksheet", write_ws_xlml(i, opts, wb), {"ss:Name":escapexml(wb.SheetNames[i])})); | ||||
| 	d[2] = write_sty_xlml(wb, opts); | ||||
| 	d[3] = write_names_xlml(wb, opts); | ||||
| 	return XML_HEADER + writextag("Workbook", d.join(""), { | ||||
| 		'xmlns':      XLMLNS.ss, | ||||
| 		'xmlns:o':    XLMLNS.o, | ||||
| @ -15144,7 +15203,7 @@ function parse_workbook(blob, options) { | ||||
| 	var cur_sheet = ""; | ||||
| 	var Preamble = {}; | ||||
| 	var lastcell, last_cell = "", cc, cmnt, rngC, rngR; | ||||
| 	var shared_formulae = {}; | ||||
| 	var sharedf = {}; | ||||
| 	var arrayf = []; | ||||
| 	var temp_val; | ||||
| 	var country; | ||||
| @ -15183,13 +15242,10 @@ function parse_workbook(blob, options) { | ||||
| 		} | ||||
| 		if(options.cellFormula && line.f) { | ||||
| 			for(var afi = 0; afi < arrayf.length; ++afi) { | ||||
| 				if(arrayf[afi][0].s.c > cell.c) continue; | ||||
| 				if(arrayf[afi][0].s.r > cell.r) continue; | ||||
| 				if(arrayf[afi][0].e.c < cell.c) continue; | ||||
| 				if(arrayf[afi][0].e.r < cell.r) continue; | ||||
| 				if(arrayf[afi][0].s.c > cell.c || arrayf[afi][0].s.r > cell.r) continue; | ||||
| 				if(arrayf[afi][0].e.c < cell.c || arrayf[afi][0].e.r < cell.r) continue; | ||||
| 				line.F = encode_range(arrayf[afi][0]); | ||||
| 				if(arrayf[afi][0].s.c != cell.c) delete line.f; | ||||
| 				if(arrayf[afi][0].s.r != cell.r) delete line.f; | ||||
| 				if(arrayf[afi][0].s.c != cell.c || arrayf[afi][0].s.r != cell.r) delete line.f; | ||||
| 				if(line.f) line.f = "" + stringify_formula(arrayf[afi][1], range, cell, supbooks, opts); | ||||
| 				break; | ||||
| 			} | ||||
| @ -15206,7 +15262,7 @@ function parse_workbook(blob, options) { | ||||
| 		enc: false, // encrypted
 | ||||
| 		sbcch: 0, // cch in the preceding SupBook
 | ||||
| 		snames: [], // sheetnames
 | ||||
| 		sharedf: shared_formulae, // shared formulae by address
 | ||||
| 		sharedf: sharedf, // shared formulae by address
 | ||||
| 		arrayf: arrayf, // array formulae array
 | ||||
| 		rrtabid: [], // RRTabId
 | ||||
| 		lastuser: "", // Last User from WriteAccess
 | ||||
| @ -15262,6 +15318,7 @@ function parse_workbook(blob, options) { | ||||
| 			if(R.n === 'EOF') val = R.f(blob, length, opts); | ||||
| 			else val = slurp(R, blob, length, opts); | ||||
| 			var Rn = R.n; | ||||
| 			if(file_depth == 0 && Rn != 'BOF') continue; | ||||
| 			/* nested switch statements to workaround V8 128 limit */ | ||||
| 			switch(Rn) { | ||||
| 				/* Workbook Options */ | ||||
| @ -15291,16 +15348,17 @@ wb.opts.Date1904 = Workbook.WBProps.date1904 = val; break; | ||||
| 				case 'RRTabId': opts.rrtabid = val; break; | ||||
| 				case 'WinProtect': opts.winlocked = val; break; | ||||
| 				case 'Template': break; // TODO
 | ||||
| 				case 'RefreshAll': wb.opts.RefreshAll = val; break; | ||||
| 				case 'BookBool': break; // TODO
 | ||||
| 				case 'UsesELFs': break; | ||||
| 				case 'MTRSettings': break; | ||||
| 				case 'CalcCount': wb.opts.CalcCount = val; break; | ||||
| 				case 'CalcDelta': wb.opts.CalcDelta = val; break; | ||||
| 				case 'CalcIter': wb.opts.CalcIter = val; break; | ||||
| 				case 'CalcMode': wb.opts.CalcMode = val; break; | ||||
| 				case 'CalcPrecision': wb.opts.CalcPrecision = val; break; | ||||
| 				case 'CalcSaveRecalc': wb.opts.CalcSaveRecalc = val; break; | ||||
| 				case 'RefreshAll': | ||||
| 				case 'CalcCount': | ||||
| 				case 'CalcDelta': | ||||
| 				case 'CalcIter': | ||||
| 				case 'CalcMode': | ||||
| 				case 'CalcPrecision': | ||||
| 				case 'CalcSaveRecalc': | ||||
| 					wb.opts[Rn] = val; break; | ||||
| 				case 'CalcRefMode': opts.CalcRefMode = val; break; // TODO: implement R1C1
 | ||||
| 				case 'Uncalced': break; | ||||
| 				case 'ForceFullCalculation': wb.opts.FullCalc = val; break; | ||||
| @ -15442,7 +15500,7 @@ wb.opts.Date1904 = Workbook.WBProps.date1904 = val; break; | ||||
| 						if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') { | ||||
| 							var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1]; | ||||
| 							var _fe = encode_cell({r:_fr, c:_fc}); | ||||
| 							if(shared_formulae[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); | ||||
| 							if(sharedf[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); | ||||
| 							else temp_val.F = ((options.dense ? (out[_fr]||[])[_fc]: out[_fe]) || {}).F; | ||||
| 						} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); | ||||
| 					} | ||||
| @ -15482,7 +15540,7 @@ wb.opts.Date1904 = Workbook.WBProps.date1904 = val; break; | ||||
| 					if(last_cell) { | ||||
| 						/* TODO: capture range */ | ||||
| 						if(!last_formula) break; /* technically unreachable */ | ||||
| 						shared_formulae[encode_cell(last_formula.cell)]= val[0]; | ||||
| 						sharedf[encode_cell(last_formula.cell)]= val[0]; | ||||
| 						cc = options.dense ? (out[last_formula.cell.r]||[])[last_formula.cell.c] : out[encode_cell(last_formula.cell)]; | ||||
| 						(cc||{}).f = ""+stringify_formula(val[0], range, lastcell, supbooks, opts); | ||||
| 					} | ||||
| @ -19217,11 +19275,26 @@ function sheet_to_formulae(sheet) { | ||||
| 	return cmds; | ||||
| } | ||||
| 
 | ||||
| function json_to_sheet(js, opts) { | ||||
| function sheet_add_json(_ws, js, opts) { | ||||
| 	var o = opts || {}; | ||||
| 	var ws = ({}); | ||||
| 	var offset = +!o.skipHeader; | ||||
| 	var ws = _ws || ({}); | ||||
| 	var _R = 0, _C = 0; | ||||
| 	if(ws && o.origin != null) { | ||||
| 		if(typeof o.origin == 'number') _R = o.origin; | ||||
| 		else { | ||||
| 			var _origin = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin; | ||||
| 			_R = _origin.r; _C = _origin.c; | ||||
| 		} | ||||
| 	} | ||||
| 	var cell; | ||||
| 	var range = ({s: {c:0, r:0}, e: {c:0, r:js.length}}); | ||||
| 	var range = ({s: {c:0, r:0}, e: {c:_C, r:_R + js.length - 1 + offset}}); | ||||
| 	if(ws['!ref']) { | ||||
| 		var _range = safe_decode_range(ws['!ref']); | ||||
| 		range.e.c = Math.max(range.e.c, _range.e.c); | ||||
| 		range.e.r = Math.max(range.e.r, _range.e.r); | ||||
| 		if(_R == -1) { _R = range.e.r + 1; range.e.r = _R + js.length - 1 + offset; } | ||||
| 	} | ||||
| 	var hdr = o.header || [], C = 0; | ||||
| 
 | ||||
| 	js.forEach(function (JS, R) { | ||||
| @ -19238,15 +19311,17 @@ function json_to_sheet(js, opts) { | ||||
| 				if(!o.cellDates) { t = 'n'; v = datenum(v); } | ||||
| 				z = o.dateNF || SSF._table[14]; | ||||
| 			} | ||||
| 			ws[encode_cell({c:C,r:R+1})] = cell = ({t:t, v:v}); | ||||
| 			ws[encode_cell({c:_C + C,r:_R + R + offset})] = cell = ({t:t, v:v}); | ||||
| 			if(z) cell.z = z; | ||||
| 		}); | ||||
| 	}); | ||||
| 	range.e.c = hdr.length - 1; | ||||
| 	for(C = 0; C < hdr.length; ++C) ws[encode_col(C) + "1"] = {t:'s', v:hdr[C]}; | ||||
| 	range.e.c = Math.max(range.e.c, _C + hdr.length - 1); | ||||
| 	var __R = encode_row(_R); | ||||
| 	if(offset) for(C = 0; C < hdr.length; ++C) ws[encode_col(C + _C) + __R] = {t:'s', v:hdr[C]}; | ||||
| 	ws['!ref'] = encode_range(range); | ||||
| 	return ws; | ||||
| } | ||||
| function json_to_sheet(js, opts) { return sheet_add_json(null, js, opts); } | ||||
| 
 | ||||
| var utils = { | ||||
| 	encode_col: encode_col, | ||||
| @ -19263,6 +19338,8 @@ var utils = { | ||||
| 	make_csv: sheet_to_csv, | ||||
| 	make_json: sheet_to_json, | ||||
| 	make_formulae: sheet_to_formulae, | ||||
| 	sheet_add_aoa: sheet_add_aoa, | ||||
| 	sheet_add_json: sheet_add_json, | ||||
| 	aoa_to_sheet: aoa_to_sheet, | ||||
| 	json_to_sheet: json_to_sheet, | ||||
| 	table_to_sheet: parse_dom_table, | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user