forked from sheetjs/sheetjs
		
	API Improvements
- `aoa_to_sheet` function (fixes #314 h/t @fonzy2013 @rvdwijngaard) - `writeFileAsync` function (fixes #396 h/t @barbalex) - `sheet_to_json` tests + docs + blankrows (fixes #602 h/t @EEaglehouse) - write number format scan now includes every index >= 50 - propagate SSF IE8 fixes (fixes #171 h/t @sheetjsdev) - update shim for extendscript (see #603 h/t @firas3d) - more flow type definitions
This commit is contained in:
		
							parent
							
								
									60e8905bcb
								
							
						
					
					
						commit
						70c48a74b9
					
				
							
								
								
									
										54
									
								
								README.md
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										54
									
								
								README.md
									
									
									
									
									
								
							| @ -49,6 +49,7 @@ with a unified JS representation, and ES3/ES5 browser compatibility back to IE6. | ||||
|   * [Supported Output Formats](#supported-output-formats) | ||||
|   * [Output Type](#output-type) | ||||
| - [Utility Functions](#utility-functions) | ||||
|   * [Array of Arrays Input](#array-of-arrays-input) | ||||
|   * [Formulae Output](#formulae-output) | ||||
|   * [CSV and general DSV Output](#csv-and-general-dsv-output) | ||||
|   * [JSON](#json) | ||||
| @ -98,6 +99,7 @@ CDNjs automatically pulls the latest version and makes all versions available at | ||||
| 
 | ||||
| The `demos` directory includes sample projects for: | ||||
| 
 | ||||
| - [`angular`](demos/angular/) | ||||
| - [`browserify`](demos/browserify/) | ||||
| - [`requirejs`](demos/requirejs/) | ||||
| - [`systemjs`](demos/systemjs/) | ||||
| @ -377,12 +379,19 @@ Parse options are described in the [Parsing Options](#parsing-options) section. | ||||
| 
 | ||||
| `XLSX.writeFile(wb, filename, write_opts)` attempts to write `wb` to `filename` | ||||
| 
 | ||||
| `XLSX.writeFileAsync(filename, wb, o, cb)` attempts to write `wb` to `filename`. | ||||
| If `o` is omitted, the writer will use the third argument as the callback. | ||||
| 
 | ||||
| Write options are described in the [Writing Options](#writing-options) section. | ||||
| 
 | ||||
| ### Utilities | ||||
| 
 | ||||
| Utilities are available in the `XLSX.utils` object: | ||||
| 
 | ||||
| **Importing:** | ||||
| 
 | ||||
| - `aoa_to_sheet` converts an array of arrays of JS data to a worksheet. | ||||
| 
 | ||||
| **Exporting:** | ||||
| 
 | ||||
| - `sheet_to_json` converts a worksheet object to an array of JSON objects. | ||||
| @ -655,7 +664,7 @@ objects which have the following properties: | ||||
| ```typescript | ||||
| type ColInfo = { | ||||
| 	MDW?:number;  // Excel's "Max Digit Width" unit, always integral | ||||
| 	width:number; // width in Excel's "Max Digit Width", width*256 is integral  | ||||
| 	width:number; // width in Excel's "Max Digit Width", width*256 is integral | ||||
| 	wpx?:number;  // width in screen pixels | ||||
| 	wch?:number;  // intermediate character calculation | ||||
| }; | ||||
| @ -666,7 +675,8 @@ follow the priority order: | ||||
| 
 | ||||
| 1) use `width` field if available | ||||
| 2) use `wpx` pixel width if available | ||||
| 2) use `wch` character count if available | ||||
| 3) use `wch` character count if available | ||||
| 
 | ||||
| ## Parsing Options | ||||
| 
 | ||||
| The exported `read` and `readFile` functions accept an options argument: | ||||
| @ -674,7 +684,7 @@ The exported `read` and `readFile` functions accept an options argument: | ||||
| | Option Name | Default | Description                                          | | ||||
| | :---------- | ------: | :--------------------------------------------------- | | ||||
| | type        |         | Input data encoding (see Input Type below)           | | ||||
| | cellFormula | true    | Save formulae to the .f field **                     | | ||||
| | cellFormula | true    | Save formulae to the .f field                        | | ||||
| | cellHTML    | true    | Parse rich text and save HTML to the .h field        | | ||||
| | cellNF      | false   | Save number format string to the .z field            | | ||||
| | cellStyles  | false   | Save style/theme info to the .s field                | | ||||
| @ -689,8 +699,6 @@ The exported `read` and `readFile` functions accept an options argument: | ||||
| | password    | ""      | If defined and file is encrypted, use password **    | | ||||
| | WTF         | false   | If true, throw errors on unexpected file features ** | | ||||
| 
 | ||||
| - `cellFormula` option only applies to formats that require extra processing to | ||||
|   parse formulae (XLS/XLSB). | ||||
| - Even if `cellNF` is false, formatted text will be generated and saved to `.w` | ||||
| - In some cases, sheets may be parsed even if `bookSheets` is false. | ||||
| - `bookSheets` and `bookProps` combine to give both sets of information | ||||
| @ -794,6 +802,8 @@ The `type` argument for `write` mirrors the `type` argument for `read`: | ||||
| 
 | ||||
| The `sheet_to_*` functions accept a worksheet and an optional options object. | ||||
| 
 | ||||
| The `*_to_sheet` functions accept a data object and an optional options object. | ||||
| 
 | ||||
| The examples are based on the following worksheet: | ||||
| 
 | ||||
| ``` | ||||
| @ -804,6 +814,30 @@ XXX| A | B | C | D | E | F | G | | ||||
|  3 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | | ||||
| ``` | ||||
| 
 | ||||
| ### Array of Arrays Input | ||||
| 
 | ||||
| `XLSX.utils.aoa_to_sheet` takes an array of arrays of JS values and returns a | ||||
| worksheet resembling the input data.  Numbers, Booleans and Strings are stored | ||||
| as the corresponding styles.  Dates are stored as date or numbers.  Array holes | ||||
| and explicit `undefined` values are skipped.  `null` values may be stubbed. All | ||||
| other values are stored as strings.  The function takes 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   | | ||||
| 
 | ||||
| To generate the example sheet: | ||||
| 
 | ||||
| ```js | ||||
| var ws = XLSX.utils.aoa_to_sheet([ | ||||
| 	"SheetJS".split(""), | ||||
| 	[1,2,3,4,5,6,7], | ||||
| 	[2,3,4,5,6,7,8] | ||||
| ]); | ||||
| ``` | ||||
| 
 | ||||
| ### Formulae Output | ||||
| 
 | ||||
| `XLSX.utils.sheet_to_formulae` generates an array of commands that represent | ||||
| @ -828,8 +862,10 @@ produces CSV output.  The function takes an options argument: | ||||
| | RS          |  `"\n"`  | "Record Separator" delimiter between rows           | | ||||
| | dateNF      |  fmt 14  | Use specified date format in string output          | | ||||
| | strip       |  false   | Remove trailing field separators in each record **  | | ||||
| | blankrows   |  true    | Include blank lines in the CSV output               | | ||||
| 
 | ||||
| - `strip` will remove trailing commas from each line under default `FS/RS` | ||||
| - blankrows must be set to `false` to skip blank lines. | ||||
| 
 | ||||
| For the example sheet: | ||||
| 
 | ||||
| @ -858,6 +894,7 @@ generate different types of JS objects.  The function takes an options argument: | ||||
| | header      |          | Control output format (see table below)             | | ||||
| | dateNF      |  fmt 14  | Use specified date format in string output          | | ||||
| | defval      |          | Use specified value in place of null or undefined   | | ||||
| | blankrows   |    **    | Include blank lines in the output **                | | ||||
| 
 | ||||
| - `raw` only affects cells which have a format code (`.z`) field or a formatted | ||||
|   text (`.w`) field. | ||||
| @ -869,6 +906,10 @@ generate different types of JS objects.  The function takes an options argument: | ||||
| - `null` values are returned when `raw` is true but are skipped when false. | ||||
| - If `defval` is not specified, null and undefined values are skipped normally. | ||||
|   If specified, all null and undefined points will be filled with `defval` | ||||
| - When `header` is `1`, the default is to generate blank rows.  `blankrows` must | ||||
|   be set to `false` to skip blank rows. | ||||
| - When `header` is not `1`, the default is to skip blank rows.  `blankrows` must | ||||
|   be truthy to generate blank rows | ||||
| 
 | ||||
| `range` is expected to be one of: | ||||
| 
 | ||||
| @ -887,6 +928,9 @@ generate different types of JS objects.  The function takes an options argument: | ||||
| | array of strings | Use specified strings as keys in row objects              | | ||||
| | (default)        | Read and disambiguate first row as keys                   | | ||||
| 
 | ||||
| If header is not `1`, the row object will contain the non-enumerable property | ||||
| `__rowNum__` that represents the row of the sheet corresponding to the entry. | ||||
| 
 | ||||
| For the example sheet: | ||||
| 
 | ||||
| ```js | ||||
|  | ||||
| @ -332,7 +332,7 @@ function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string | ||||
| 	if(fmt.charCodeAt(fmt.length - 1) === 44) return write_num_cm(type, fmt, val); | ||||
| 	if(fmt.indexOf('%') !== -1) return write_num_pct(type, fmt, val); | ||||
| 	if(fmt.indexOf('E') !== -1) return write_num_exp(fmt, val); | ||||
| 	if(fmt.charCodeAt(0) === 36) return "$"+write_num_flt(type,fmt.substr(fmt[1]==' '?2:1),val); | ||||
| 	if(fmt.charCodeAt(0) === 36) return "$"+write_num_flt(type,fmt.substr(fmt.charAt(1)==' '?2:1),val); | ||||
| 	var o; | ||||
| 	var r/*:?Array<string>*/, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : ""; | ||||
| 	if(fmt.match(/^00+$/)) return sign + pad0r(aval,fmt.length); | ||||
| @ -358,7 +358,7 @@ function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string | ||||
| 	if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) { | ||||
| 		o = _strrev(write_num_flt(type, fmt.replace(/[\\-]/g,""), val)); | ||||
| 		ri = 0; | ||||
| 		return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o[ri++]:x==='0'?'0':"";})); | ||||
| 		return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o.charAt(ri++):x==='0'?'0':"";})); | ||||
| 	} | ||||
| 	if(fmt.match(phone)) { | ||||
| 		o = write_num_flt(type, "##########", val); | ||||
| @ -370,7 +370,7 @@ function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string | ||||
| 		ff = frac(aval, Math.pow(10,ri)-1, false); | ||||
| 		o = "" + sign; | ||||
| 		oa = write_num("n", /*::String(*/r[1]/*::)*/, ff[1]); | ||||
| 		if(oa[oa.length-1] == " ") oa = oa.substr(0,oa.length-1) + "0"; | ||||
| 		if(oa.charAt(oa.length-1) == " ") oa = oa.substr(0,oa.length-1) + "0"; | ||||
| 		o += oa + /*::String(*/r[2]/*::)*/ + "/" + /*::String(*/r[3]/*::)*/; | ||||
| 		oa = rpad_(ff[2],ri); | ||||
| 		if(oa.length < r[4].length) oa = hashq(r[4].substr(r[4].length-oa.length)) + oa; | ||||
| @ -441,7 +441,7 @@ function write_num_int(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string | ||||
| 	if(fmt.charCodeAt(fmt.length - 1) === 44) return write_num_cm2(type, fmt, val); | ||||
| 	if(fmt.indexOf('%') !== -1) return write_num_pct2(type, fmt, val); | ||||
| 	if(fmt.indexOf('E') !== -1) return write_num_exp2(fmt, val); | ||||
| 	if(fmt.charCodeAt(0) === 36) return "$"+write_num_int(type,fmt.substr(fmt[1]==' '?2:1),val); | ||||
| 	if(fmt.charCodeAt(0) === 36) return "$"+write_num_int(type,fmt.substr(fmt.charAt(1)==' '?2:1),val); | ||||
| 	var o; | ||||
| 	var r, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : ""; | ||||
| 	if(fmt.match(/^00+$/)) return sign + pad0(aval,fmt.length); | ||||
| @ -471,7 +471,7 @@ function write_num_int(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string | ||||
| 	if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) { | ||||
| 		o = _strrev(write_num_int(type, fmt.replace(/[\\-]/g,""), val)); | ||||
| 		ri = 0; | ||||
| 		return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o[ri++]:x==='0'?'0':"";})); | ||||
| 		return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o.charAt(ri++):x==='0'?'0':"";})); | ||||
| 	} | ||||
| 	if(fmt.match(phone)) { | ||||
| 		o = write_num_int(type, "##########", val); | ||||
| @ -483,7 +483,7 @@ function write_num_int(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string | ||||
| 		ff = frac(aval, Math.pow(10,ri)-1, false); | ||||
| 		o = "" + sign; | ||||
| 		oa = write_num("n", r[1], ff[1]); | ||||
| 		if(oa[oa.length-1] == " ") oa = oa.substr(0,oa.length-1) + "0"; | ||||
| 		if(oa.charAt(oa.length-1) == " ") oa = oa.substr(0,oa.length-1) + "0"; | ||||
| 		o += oa + r[2] + "/" + r[3]; | ||||
| 		oa = rpad_(ff[2],ri); | ||||
| 		if(oa.length < r[4].length) oa = hashq(r[4].substr(r[4].length-oa.length)) + oa; | ||||
| @ -735,7 +735,7 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) { | ||||
| 				j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")-1:out[i].v.length-1; | ||||
| 				vv = out[i].v.substr(j+1); | ||||
| 				for(; j>=0; --j) { | ||||
| 					if(jj>=0 && (out[i].v[j] === "0" || out[i].v[j] === "#")) vv = ostr[jj--] + vv; | ||||
| 					if(jj>=0 && (out[i].v.charAt(j) === "0" || out[i].v.charAt(j) === "#")) vv = ostr.charAt(jj--) + vv; | ||||
| 				} | ||||
| 				out[i].v = vv; | ||||
| 				out[i].t = 't'; | ||||
| @ -748,7 +748,7 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) { | ||||
| 				j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")+1:0; | ||||
| 				vv = out[i].v.substr(0,j); | ||||
| 				for(; j<out[i].v.length; ++j) { | ||||
| 					if(jj<ostr.length) vv += ostr[jj++]; | ||||
| 					if(jj<ostr.length) vv += ostr.charAt(jj++); | ||||
| 				} | ||||
| 				out[i].v = vv; | ||||
| 				out[i].t = 't'; | ||||
|  | ||||
| @ -34,6 +34,18 @@ function datenum(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ { | ||||
| 	if(date1904) epoch += 1462*24*60*60*1000; | ||||
| 	return (epoch + 2209161600000) / (24 * 60 * 60 * 1000); | ||||
| } | ||||
| function numdate(v/*:number*/)/*:Date*/ { | ||||
| 	var date = SSF.parse_date_code(v); | ||||
| 	var val = new Date(); | ||||
| 	if(date == null) throw new Error("Bad Date Code: " + v); | ||||
| 	val.setUTCDate(date.d); | ||||
| 	val.setUTCMonth(date.m-1); | ||||
| 	val.setUTCFullYear(date.y); | ||||
| 	val.setUTCHours(date.H); | ||||
| 	val.setUTCMinutes(date.M); | ||||
| 	val.setUTCSeconds(date.S); | ||||
| 	return val; | ||||
| } | ||||
| 
 | ||||
| /* ISO 8601 Duration */ | ||||
| function parse_isodur(s) { | ||||
|  | ||||
							
								
								
									
										36
									
								
								bits/27_csfutils.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										36
									
								
								bits/27_csfutils.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| function sheet_to_workbook(sheet/*:Worksheet*/, opts)/*:Workbook*/ { | ||||
| 	var n = opts && opts.sheet ? opts.sheet : "Sheet1"; | ||||
| 	var sheets = {}; sheets[n] = sheet; | ||||
| 	return { SheetNames: [n], Sheets: sheets }; | ||||
| } | ||||
| 
 | ||||
| function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ { | ||||
| 	var o = opts || {}; | ||||
| 	var ws/*:Worksheet*/ = ({}/*:any*/); | ||||
| 	var range/*:Range*/ = ({s: {c:10000000, r:10000000}, e: {c:0, r:0}}/*:any*/); | ||||
| 	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(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 cell_ref = encode_cell(({c:C,r:R}/*:any*/)); | ||||
| 			if(cell.v === null) { if(!o.cellStubs) continue; cell.t = 'z'; } | ||||
| 			else if(typeof cell.v === 'number') cell.t = 'n'; | ||||
| 			else if(typeof cell.v === 'boolean') cell.t = 'b'; | ||||
| 			else if(cell.v instanceof Date) { | ||||
| 				cell.z = o.dateNF || SSF._table[14]; | ||||
| 				if(o.cellDates) cell.t = 'd'; | ||||
| 				else { cell.t = 'n'; cell.v = datenum(cell.v); } | ||||
| 				cell.w = SSF.format(cell.z, cell.v); | ||||
| 			} | ||||
| 			else cell.t = 's'; | ||||
| 			ws[cell_ref] = cell; | ||||
| 		} | ||||
| 	} | ||||
| 	if(range.s.c < 10000000) ws['!ref'] = encode_range(range); | ||||
| 	return ws; | ||||
| } | ||||
| 
 | ||||
| @ -222,7 +222,7 @@ function parse_numFmts(t, styles, opts) { | ||||
| 
 | ||||
| function write_numFmts(NF/*:{[n:number]:string}*/, opts) { | ||||
| 	var o = ["<numFmts>"]; | ||||
| 	[[5,8],[23,26],[41,44],[63,66],[164,392]].forEach(function(r) { | ||||
| 	[[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) { | ||||
| 		for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) o[o.length] = (writextag('numFmt',null,{numFmtId:i,formatCode:escapexml(NF[i])})); | ||||
| 	}); | ||||
| 	if(o.length === 1) return ""; | ||||
|  | ||||
| @ -806,18 +806,18 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks, | ||||
| 			/* 2.5.198.31 TODO */ | ||||
| 			case 'PtgAreaN': | ||||
| 				type = f[1][0]; r = shift_range_xls(f[1][1], _range, opts); | ||||
| 				stack.push(encode_range_xls(r, opts)); | ||||
| 				stack.push(encode_range_xls((r/*:any*/), opts)); | ||||
| 				break; | ||||
| 			/* 2.5.198.27 TODO: fixed points */ | ||||
| 			case 'PtgArea': | ||||
| 				type = f[1][0]; r = shift_range_xls(f[1][1], _range, opts); | ||||
| 				stack.push(encode_range_xls(r, opts)); | ||||
| 				stack.push(encode_range_xls((r/*:any*/), opts)); | ||||
| 				break; | ||||
| 			/* 2.5.198.28 */ | ||||
| 			case 'PtgArea3d': // TODO: lots of stuff
 | ||||
| 				type = f[1][0]; ixti = /*::Number(*/f[1][1]/*::)*/; r = f[1][2]; | ||||
| 				sname = (supbooks && supbooks[1] ? supbooks[1][ixti+1] : "**MISSING**"); | ||||
| 				stack.push(sname + "!" + encode_range(r)); | ||||
| 				stack.push(sname + "!" + encode_range((r/*:any*/))); | ||||
| 				break; | ||||
| 			/* 2.5.198.41 */ | ||||
| 			case 'PtgAttrSum': | ||||
|  | ||||
| @ -167,6 +167,7 @@ function xlml_normalize(d)/*:string*/ { | ||||
| var xlmlregex = /<(\/?)([^\s?>!\/:]*:|)([^\s?>]*[^\s?>\/])[^>]*>/mg; | ||||
| //var xlmlregex = /<(\/?)([a-z0-9]*:|)(\w+)[^>]*>/mg;
 | ||||
| function parse_xlml_xml(d, opts)/*:Workbook*/ { | ||||
| 	make_ssf(SSF); | ||||
| 	var str = debom(xlml_normalize(d)); | ||||
| 	if(opts && opts.type == 'binary' && typeof cptable !== 'undefined') str = cptable.utils.decode(65001, char_codes(str)); | ||||
| 	if(str.substr(0,1000).indexOf("<html") >= 0) return parse_html(str, opts); | ||||
| @ -277,7 +278,10 @@ function parse_xlml_xml(d, opts)/*:Workbook*/ { | ||||
| 			break; | ||||
| 
 | ||||
| 		case 'NumberFormat': | ||||
| 			stag.nf = xlml_parsexmltag(Rn[0]).Format || "General"; | ||||
| 			stag.nf = unescapexml(xlml_parsexmltag(Rn[0]).Format || "General"); | ||||
| 			if(XLMLFormatMap[stag.nf]) stag.nf = XLMLFormatMap[stag.nf]; | ||||
| 			for(var ssfidx = 0; ssfidx != 0x188; ++ssfidx) if(SSF._table[ssfidx] == stag.nf) break; | ||||
| 			if(ssfidx == 0x188) for(ssfidx = 0x39; ssfidx != 0x188; ++ssfidx) if(SSF._table[ssfidx] == null) { SSF.load(stag.nf, ssfidx); break; } | ||||
| 			break; | ||||
| 
 | ||||
| 		case 'Column': | ||||
|  | ||||
| @ -85,7 +85,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 	var out = {}; | ||||
| 	var Directory = {}; | ||||
| 	var found_sheet = false; | ||||
| 	var range = {}; | ||||
| 	var range/*:Range*/ = ({}/*:any*/); | ||||
| 	var last_formula = null; | ||||
| 	var sst = []; | ||||
| 	var cur_sheet = ""; | ||||
|  | ||||
| @ -59,9 +59,7 @@ function writeSync(wb/*:Workbook*/, opts/*:?WriteOpts*/) { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| function writeFileSync(wb/*:Workbook*/, filename/*:string*/, opts/*:?WriteFileOpts*/) { | ||||
| 	var o = opts||{}; o.type = 'file'; | ||||
| 	o.file = filename; | ||||
| function resolve_book_type(o/*?WriteFileOpts*/) { | ||||
| 	if(!o.bookType) switch(o.file.slice(-5).toLowerCase()) { | ||||
| 		case '.xlsx': o.bookType = 'xlsx'; break; | ||||
| 		case '.xlsm': o.bookType = 'xlsm'; break; | ||||
| @ -74,6 +72,20 @@ function writeFileSync(wb/*:Workbook*/, filename/*:string*/, opts/*:?WriteFileOp | ||||
| 		case '.ods': o.bookType = 'ods'; break; | ||||
| 		case '.csv': o.bookType = 'csv'; break; | ||||
| 	}} | ||||
| } | ||||
| 
 | ||||
| function writeFileSync(wb/*:Workbook*/, filename/*:string*/, opts/*:?WriteFileOpts*/) { | ||||
| 	var o = opts||{}; o.type = 'file'; | ||||
| 	o.file = filename; | ||||
| 	resolve_book_type(o); | ||||
| 	return writeSync(wb, o); | ||||
| } | ||||
| 
 | ||||
| function writeFileAsync(filename/*:string*/, wb/*:Workbook*/, opts/*:?WriteFileOpts*/, cb/*:?(e?:ErrnoError)=>void*/) { | ||||
| 	var o = opts||{}; o.type = 'file'; | ||||
| 	o.file = filename; | ||||
| 	resolve_book_type(o); | ||||
| 	o.type = 'buffer'; | ||||
| 	var _cb = cb; if(!(_cb instanceof Function)) _cb = (opts/*:any*/); | ||||
| 	return _fs.writeFile(filename, writeSync(wb, o), _cb); | ||||
| } | ||||
|  | ||||
| @ -14,7 +14,8 @@ function encode_cell(cell/*:CellAddress*/)/*:string*/ { return encode_col(cell.c | ||||
| function fix_cell(cstr/*:string*/)/*:string*/ { return fix_col(fix_row(cstr)); } | ||||
| function unfix_cell(cstr/*:string*/)/*:string*/ { return unfix_col(unfix_row(cstr)); } | ||||
| function decode_range(range/*:string*/)/*:Range*/ { var x =range.split(":").map(decode_cell); return {s:x[0],e:x[x.length-1]}; } | ||||
| function encode_range(cs/*:any*/,ce/*:?any*/)/*:string*/ { | ||||
| /*# if only one arg, it is assumed to be a Range.  If 2 args, both are cell addresses */ | ||||
| function encode_range(cs/*:CellAddrSpec|Range*/,ce/*:?CellAddrSpec*/)/*:string*/ { | ||||
| 	if(typeof ce === 'undefined' || typeof ce === 'number') { | ||||
| /*:: if(!(cs instanceof Range)) throw "unreachable"; */ | ||||
| 		return encode_range(cs.s, cs.e); | ||||
| @ -69,8 +70,8 @@ function format_cell(cell/*:Cell*/, v/*:any*/, o/*:any*/) { | ||||
| 	if(cell == null || cell.t == null || cell.t == 'z') return ""; | ||||
| 	if(cell.w !== undefined) return cell.w; | ||||
| 	if(cell.t == 'd' && !cell.z && o && o.dateNF) cell.z = o.dateNF; | ||||
| 	if(v == undefined) return safe_format_cell(cell, cell.v); | ||||
| 	return safe_format_cell(cell, v); | ||||
| 	if(v == undefined) return safe_format_cell(cell, cell.v, o); | ||||
| 	return safe_format_cell(cell, v, o); | ||||
| } | ||||
| 
 | ||||
| function sheet_to_json(sheet/*:Worksheet*/, opts/*:?Sheet2JSONOpts*/){ | ||||
| @ -102,7 +103,7 @@ function sheet_to_json(sheet/*:Worksheet*/, opts/*:?Sheet2JSONOpts*/){ | ||||
| 			case 3: hdr[C] = o.header[C - r.s.c]; break; | ||||
| 			default: | ||||
| 				if(val == null) continue; | ||||
| 				vv = v = format_cell(val); | ||||
| 				vv = v = format_cell(val, null, o); | ||||
| 				var counter = 0; | ||||
| 				for(var CC = 0; CC < hdr.length; ++CC) if(hdr[CC] == vv) vv = v + "_" + (++counter); | ||||
| 				hdr[C] = vv; | ||||
| @ -138,19 +139,17 @@ function sheet_to_json(sheet/*:Worksheet*/, opts/*:?Sheet2JSONOpts*/){ | ||||
| 					else if(raw && v === null) row[hdr[C]] = null; | ||||
| 					else continue; | ||||
| 				} else { | ||||
| 					row[hdr[C]] = raw ? v : format_cell(val,v); | ||||
| 					row[hdr[C]] = raw ? v : format_cell(val,v,o); | ||||
| 				} | ||||
| 				isempty = false; | ||||
| 			} | ||||
| 		} | ||||
| 		if(isempty === false || header === 1) out[outi++] = row; | ||||
| 		if((isempty === false) || (header === 1 ? o.blankrows !== false : !!o.blankrows)) out[outi++] = row; | ||||
| 	} | ||||
| 	out.length = outi; | ||||
| 	return out; | ||||
| } | ||||
| 
 | ||||
| function sheet_to_row_object_array(sheet/*:Worksheet*/, opts/*:?Sheet2JSONOpts*/) { return sheet_to_json(sheet, opts != null ? opts : {}); } | ||||
| 
 | ||||
| function sheet_to_csv(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) { | ||||
| 	var out = "", txt = "", qreg = /"/g; | ||||
| 	var o = opts == null ? {} : opts; | ||||
| @ -158,27 +157,31 @@ function sheet_to_csv(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) { | ||||
| 	var r = safe_decode_range(sheet["!ref"]); | ||||
| 	var FS = o.FS !== undefined ? o.FS : ",", fs = FS.charCodeAt(0); | ||||
| 	var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0); | ||||
| 	var endregex = new RegExp(FS+"+$"); | ||||
| 	var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$"); | ||||
| 	var row = "", rr = "", cols = []; | ||||
| 	var i = 0, cc = 0, val; | ||||
| 	var R = 0, C = 0; | ||||
| 	for(C = r.s.c; C <= r.e.c; ++C) cols[C] = encode_col(C); | ||||
| 	for(R = r.s.r; R <= r.e.r; ++R) { | ||||
| 		var isempty = true; | ||||
| 		row = ""; | ||||
| 		rr = encode_row(R); | ||||
| 		for(C = r.s.c; C <= r.e.c; ++C) { | ||||
| 			val = sheet[cols[C] + rr]; | ||||
| 			if(val == null) txt = ""; | ||||
| 			else if(val.v != null) { | ||||
| 				txt = ''+format_cell(val); | ||||
| 				isempty = false; | ||||
| 				txt = ''+format_cell(val, null, o); | ||||
| 				for(i = 0, cc = 0; i !== txt.length; ++i) if((cc = txt.charCodeAt(i)) === fs || cc === rs || cc === 34) { | ||||
| 					txt = "\"" + txt.replace(qreg, '""') + "\""; break; } | ||||
| 			} else if(val.f != null && !val.F) { | ||||
| 				isempty = false; | ||||
| 				txt = '=' + val.f; if(txt.indexOf(",") >= 0) txt = '"' + txt.replace(qreg, '""') + '"'; | ||||
| 			} else txt = ""; | ||||
| 			/* NOTE: Excel CSV does not support array formulae */ | ||||
| 			row += (C === r.s.c ? "" : FS) + txt; | ||||
| 		} | ||||
| 		if(o.blankrows === false && isempty) continue; | ||||
| 		if(o.strip) row = row.replace(endregex,""); | ||||
| 		out += row + RS; | ||||
| 	} | ||||
| @ -236,8 +239,9 @@ var utils = { | ||||
| 	make_csv: sheet_to_csv, | ||||
| 	make_json: sheet_to_json, | ||||
| 	make_formulae: sheet_to_formulae, | ||||
| 	aoa_to_sheet: aoa_to_sheet, | ||||
| 	sheet_to_csv: sheet_to_csv, | ||||
| 	sheet_to_json: sheet_to_json, | ||||
| 	sheet_to_formulae: sheet_to_formulae, | ||||
| 	sheet_to_row_object_array: sheet_to_row_object_array | ||||
| 	sheet_to_row_object_array: sheet_to_json | ||||
| }; | ||||
|  | ||||
| @ -9,6 +9,7 @@ XLSX.readFileSync = readFileSync; | ||||
| XLSX.write = writeSync; | ||||
| XLSX.writeFile = writeFileSync; | ||||
| XLSX.writeFileSync = writeFileSync; | ||||
| XLSX.writeFileAsync = writeFileAsync; | ||||
| XLSX.utils = utils; | ||||
| XLSX.CFB = CFB; | ||||
| XLSX.SSF = SSF; | ||||
|  | ||||
| @ -25,6 +25,7 @@ CDNjs automatically pulls the latest version and makes all versions available at | ||||
| 
 | ||||
| The `demos` directory includes sample projects for: | ||||
| 
 | ||||
| - [`angular`](demos/angular/) | ||||
| - [`browserify`](demos/browserify/) | ||||
| - [`requirejs`](demos/requirejs/) | ||||
| - [`systemjs`](demos/systemjs/) | ||||
|  | ||||
| @ -20,12 +20,19 @@ Parse options are described in the [Parsing Options](#parsing-options) section. | ||||
| 
 | ||||
| `XLSX.writeFile(wb, filename, write_opts)` attempts to write `wb` to `filename` | ||||
| 
 | ||||
| `XLSX.writeFileAsync(filename, wb, o, cb)` attempts to write `wb` to `filename`. | ||||
| If `o` is omitted, the writer will use the third argument as the callback. | ||||
| 
 | ||||
| Write options are described in the [Writing Options](#writing-options) section. | ||||
| 
 | ||||
| ### Utilities | ||||
| 
 | ||||
| Utilities are available in the `XLSX.utils` object: | ||||
| 
 | ||||
| **Importing:** | ||||
| 
 | ||||
| - `aoa_to_sheet` converts an array of arrays of JS data to a worksheet. | ||||
| 
 | ||||
| **Exporting:** | ||||
| 
 | ||||
| - `sheet_to_json` converts a worksheet object to an array of JSON objects. | ||||
|  | ||||
| @ -17,7 +17,7 @@ objects which have the following properties: | ||||
| ```typescript | ||||
| type ColInfo = { | ||||
| 	MDW?:number;  // Excel's "Max Digit Width" unit, always integral | ||||
| 	width:number; // width in Excel's "Max Digit Width", width*256 is integral  | ||||
| 	width:number; // width in Excel's "Max Digit Width", width*256 is integral | ||||
| 	wpx?:number;  // width in screen pixels | ||||
| 	wch?:number;  // intermediate character calculation | ||||
| }; | ||||
| @ -28,4 +28,5 @@ follow the priority order: | ||||
| 
 | ||||
| 1) use `width` field if available | ||||
| 2) use `wpx` pixel width if available | ||||
| 2) use `wch` character count if available | ||||
| 3) use `wch` character count if available | ||||
| 
 | ||||
|  | ||||
| @ -5,7 +5,7 @@ The exported `read` and `readFile` functions accept an options argument: | ||||
| | Option Name | Default | Description                                          | | ||||
| | :---------- | ------: | :--------------------------------------------------- | | ||||
| | type        |         | Input data encoding (see Input Type below)           | | ||||
| | cellFormula | true    | Save formulae to the .f field **                     | | ||||
| | cellFormula | true    | Save formulae to the .f field                        | | ||||
| | cellHTML    | true    | Parse rich text and save HTML to the .h field        | | ||||
| | cellNF      | false   | Save number format string to the .z field            | | ||||
| | cellStyles  | false   | Save style/theme info to the .s field                | | ||||
| @ -20,8 +20,6 @@ The exported `read` and `readFile` functions accept an options argument: | ||||
| | password    | ""      | If defined and file is encrypted, use password **    | | ||||
| | WTF         | false   | If true, throw errors on unexpected file features ** | | ||||
| 
 | ||||
| - `cellFormula` option only applies to formats that require extra processing to | ||||
|   parse formulae (XLS/XLSB). | ||||
| - Even if `cellNF` is false, formatted text will be generated and saved to `.w` | ||||
| - In some cases, sheets may be parsed even if `bookSheets` is false. | ||||
| - `bookSheets` and `bookProps` combine to give both sets of information | ||||
|  | ||||
| @ -2,6 +2,8 @@ | ||||
| 
 | ||||
| The `sheet_to_*` functions accept a worksheet and an optional options object. | ||||
| 
 | ||||
| The `*_to_sheet` functions accept a data object and an optional options object. | ||||
| 
 | ||||
| The examples are based on the following worksheet: | ||||
| 
 | ||||
| ``` | ||||
| @ -12,6 +14,30 @@ XXX| A | B | C | D | E | F | G | | ||||
|  3 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | | ||||
| ``` | ||||
| 
 | ||||
| ### Array of Arrays Input | ||||
| 
 | ||||
| `XLSX.utils.aoa_to_sheet` takes an array of arrays of JS values and returns a | ||||
| worksheet resembling the input data.  Numbers, Booleans and Strings are stored | ||||
| as the corresponding styles.  Dates are stored as date or numbers.  Array holes | ||||
| and explicit `undefined` values are skipped.  `null` values may be stubbed. All | ||||
| other values are stored as strings.  The function takes 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   | | ||||
| 
 | ||||
| To generate the example sheet: | ||||
| 
 | ||||
| ```js | ||||
| var ws = XLSX.utils.aoa_to_sheet([ | ||||
| 	"SheetJS".split(""), | ||||
| 	[1,2,3,4,5,6,7], | ||||
| 	[2,3,4,5,6,7,8] | ||||
| ]); | ||||
| ``` | ||||
| 
 | ||||
| ### Formulae Output | ||||
| 
 | ||||
| `XLSX.utils.sheet_to_formulae` generates an array of commands that represent | ||||
| @ -36,8 +62,10 @@ produces CSV output.  The function takes an options argument: | ||||
| | RS          |  `"\n"`  | "Record Separator" delimiter between rows           | | ||||
| | dateNF      |  fmt 14  | Use specified date format in string output          | | ||||
| | strip       |  false   | Remove trailing field separators in each record **  | | ||||
| | blankrows   |  true    | Include blank lines in the CSV output               | | ||||
| 
 | ||||
| - `strip` will remove trailing commas from each line under default `FS/RS` | ||||
| - blankrows must be set to `false` to skip blank lines. | ||||
| 
 | ||||
| For the example sheet: | ||||
| 
 | ||||
| @ -66,6 +94,7 @@ generate different types of JS objects.  The function takes an options argument: | ||||
| | header      |          | Control output format (see table below)             | | ||||
| | dateNF      |  fmt 14  | Use specified date format in string output          | | ||||
| | defval      |          | Use specified value in place of null or undefined   | | ||||
| | blankrows   |    **    | Include blank lines in the output **                | | ||||
| 
 | ||||
| - `raw` only affects cells which have a format code (`.z`) field or a formatted | ||||
|   text (`.w`) field. | ||||
| @ -77,6 +106,10 @@ generate different types of JS objects.  The function takes an options argument: | ||||
| - `null` values are returned when `raw` is true but are skipped when false. | ||||
| - If `defval` is not specified, null and undefined values are skipped normally. | ||||
|   If specified, all null and undefined points will be filled with `defval` | ||||
| - When `header` is `1`, the default is to generate blank rows.  `blankrows` must | ||||
|   be set to `false` to skip blank rows. | ||||
| - When `header` is not `1`, the default is to skip blank rows.  `blankrows` must | ||||
|   be truthy to generate blank rows | ||||
| 
 | ||||
| `range` is expected to be one of: | ||||
| 
 | ||||
| @ -95,6 +128,9 @@ generate different types of JS objects.  The function takes an options argument: | ||||
| | array of strings | Use specified strings as keys in row objects              | | ||||
| | (default)        | Read and disambiguate first row as keys                   | | ||||
| 
 | ||||
| If header is not `1`, the row object will contain the non-enumerable property | ||||
| `__rowNum__` that represents the row of the sheet corresponding to the entry. | ||||
| 
 | ||||
| For the example sheet: | ||||
| 
 | ||||
| ```js | ||||
|  | ||||
							
								
								
									
										6
									
								
								jszip.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										6
									
								
								jszip.js
									
									
									
									
									
								
							| @ -9,7 +9,7 @@ Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/js | ||||
| JSZip uses the library pako released under the MIT license : | ||||
| https://github.com/nodeca/pako/blob/master/LICENSE
 | ||||
| */ | ||||
| !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd){JSZip=e();define([],e);}else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.JSZip=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ | ||||
| !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd){JSZip=e();define([],e);}else{if(typeof self == 'undefined' && typeof app != 'undefined') self = app;var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.JSZip=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ | ||||
| 'use strict'; | ||||
| // private property
 | ||||
| var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; | ||||
| @ -1005,10 +1005,6 @@ var generateZipParts = function(name, file, compressedObject, offset) { | ||||
|         date = o.date; | ||||
|     } | ||||
| 
 | ||||
|     // date
 | ||||
|     // @see http://www.delorie.com/djgpp/doc/rbinter/it/52/13.html
 | ||||
|     // @see http://www.delorie.com/djgpp/doc/rbinter/it/65/16.html
 | ||||
|     // @see http://www.delorie.com/djgpp/doc/rbinter/it/66/16.html
 | ||||
| 
 | ||||
|     dosTime = date.getHours(); | ||||
|     dosTime = dosTime << 6; | ||||
|  | ||||
| @ -25,6 +25,7 @@ interface CellAddress { | ||||
| 	r:number; | ||||
| 	c:number; | ||||
| }; | ||||
| type CellAddrSpec = CellAddress | string; | ||||
| 
 | ||||
| type Cell = any; | ||||
| 
 | ||||
| @ -66,4 +67,6 @@ type ColInfo = { | ||||
| 	wpx?:number;  // width in screen pixels
 | ||||
| 	wch?:number;  // intermediate character calculation
 | ||||
| }; | ||||
| 
 | ||||
| type AOA = Array<Array<any> >; | ||||
| */ | ||||
|  | ||||
							
								
								
									
										6
									
								
								shim.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										6
									
								
								shim.js
									
									
									
									
									
								
							| @ -242,7 +242,7 @@ if (typeof ArrayBuffer !== 'undefined' && !ArrayBuffer.prototype.slice) { | ||||
| 
 | ||||
| ;(function () { | ||||
| 
 | ||||
|   var object = typeof exports != 'undefined' ? exports : self; // #8: web workers
 | ||||
|   var object = typeof exports != 'undefined' ? exports : typeof self != 'undefined' ? self : (1,eval)("this"); | ||||
|   var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; | ||||
| 
 | ||||
|   function InvalidCharacterError(message) { | ||||
| @ -279,7 +279,7 @@ if (typeof ArrayBuffer !== 'undefined' && !ArrayBuffer.prototype.slice) { | ||||
|   // [https://gist.github.com/1020396] by [https://github.com/atk]
 | ||||
|   object.atob || ( | ||||
|   object.atob = function (input) { | ||||
|     var str = String(input).replace(/=+$/, ''); | ||||
|     var str = String(input).replace(new RegExp("=+$"), ''); | ||||
|     if (str.length % 4 == 1) { | ||||
|       throw new InvalidCharacterError("'atob' failed: The string to be decoded is not correctly encoded."); | ||||
|     } | ||||
| @ -299,7 +299,7 @@ if (typeof ArrayBuffer !== 'undefined' && !ArrayBuffer.prototype.slice) { | ||||
|     } | ||||
|     return output; | ||||
|   }); | ||||
| 
 | ||||
|   if(typeof app != 'undefined') { app.btoa = object.btoa; app.atob = object.atob; } | ||||
| }()); | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										107
									
								
								test.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										107
									
								
								test.js
									
									
									
									
									
								
							| @ -1041,33 +1041,6 @@ function datenum(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ { | ||||
| 	if(date1904) epoch += 1462*24*60*60*1000; | ||||
| 	return (epoch + 2209161600000) / (24 * 60 * 60 * 1000); | ||||
| } | ||||
| function sheet_from_array_of_arrays(data, opts) { | ||||
| 	var ws = {}; | ||||
| 	var range = {s: {c:10000000, r:10000000}, e: {c:0, r:0 }}; | ||||
| 	for(var R = 0; R != data.length; ++R) { | ||||
| 		for(var C = 0; C != data[R].length; ++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; | ||||
| 			var cell = {v: data[R][C] }; | ||||
| 			if(cell.v === undefined) continue; | ||||
| 			var cell_ref = X.utils.encode_cell({c:C,r:R}); | ||||
| 			if(cell.v === null) cell.t = 'z'; | ||||
| 			else if(typeof cell.v === 'number') cell.t = 'n'; | ||||
| 			else if(typeof cell.v === 'boolean') cell.t = 'b'; | ||||
| 			else if(cell.v instanceof Date) { | ||||
| 				cell.z = X.SSF._table[14]; | ||||
| 				if(opts && opts.cellDates) cell.t = 'd'; | ||||
| 				else { cell.t = 'n'; cell.v = datenum(cell.v); } | ||||
| 			} | ||||
| 			else cell.t = 's'; | ||||
| 			ws[cell_ref] = cell; | ||||
| 		} | ||||
| 	} | ||||
| 	if(range.s.c < 10000000) ws['!ref'] = X.utils.encode_range(range); | ||||
| 	return ws; | ||||
| } | ||||
| 
 | ||||
| describe('json output', function() { | ||||
| 	function seeker(json, keys, val) { | ||||
| @ -1085,7 +1058,7 @@ describe('json output', function() { | ||||
| 			["foo", "bar", new Date("2014-02-19T14:30Z"), "0.3"], | ||||
| 			["baz", undefined, "qux"] | ||||
| 		]; | ||||
| 		ws = sheet_from_array_of_arrays(data); | ||||
| 		ws = X.utils.aoa_to_sheet(data); | ||||
| 	}); | ||||
| 	if(typeof before != 'undefined') before(bef); | ||||
| 	else it('before', bef); | ||||
| @ -1142,8 +1115,6 @@ describe('json output', function() { | ||||
| 	}); | ||||
| 	it('should use defval if requested', function() { | ||||
| 		var json = X.utils.sheet_to_json(ws, {defval: 'jimjin'}); | ||||
| 		console.log(json); | ||||
| 		console.log(ws); | ||||
| 		assert.equal(json.length, data.length - 1); | ||||
| 		assert.equal(json[0][1], "TRUE"); | ||||
| 		assert.equal(json[1][2], "bar"); | ||||
| @ -1153,13 +1124,11 @@ describe('json output', function() { | ||||
| 		assert.doesNotThrow(function() { seeker(json, [1,2,3], "sheetjs"); }); | ||||
| 		assert.throws(function() { seeker(json, [1,2,3], "baz"); }); | ||||
| 		var json = X.utils.sheet_to_json(ws, {raw:true}); | ||||
| 		console.log(json); | ||||
| 		var json = X.utils.sheet_to_json(ws, {raw:true, defval: 'jimjin'}); | ||||
| 		console.log(json); | ||||
| 	}); | ||||
| 	it('should disambiguate headers', function() { | ||||
| 		var _data = [["S","h","e","e","t","J","S"],[1,2,3,4,5,6,7],[2,3,4,5,6,7,8]]; | ||||
| 		var _ws = sheet_from_array_of_arrays(_data); | ||||
| 		var _ws = X.utils.aoa_to_sheet(_data); | ||||
| 		var json = X.utils.sheet_to_json(_ws); | ||||
| 		for(var i = 0; i < json.length; ++i) { | ||||
| 			assert.equal(json[i].S,   1 + i); | ||||
| @ -1172,7 +1141,7 @@ describe('json output', function() { | ||||
| 		} | ||||
| 	}); | ||||
| 	it('should handle raw data if requested', function() { | ||||
| 		var _ws = sheet_from_array_of_arrays(data, {cellDates:true}); | ||||
| 		var _ws = X.utils.aoa_to_sheet(data, {cellDates:true}); | ||||
| 		var json = X.utils.sheet_to_json(_ws, {header:1, raw:true}); | ||||
| 		assert.equal(json.length, data.length); | ||||
| 		assert.equal(json[1][0], true); | ||||
| @ -1181,6 +1150,72 @@ describe('json output', function() { | ||||
| 		assert.equal(json[2][2].getTime(), new Date("2014-02-19T14:30Z").getTime()); | ||||
| 		assert.equal(json[3][2], "qux"); | ||||
| 	}); | ||||
| 	it('should include __rowNum__', function() { | ||||
| 		var _data = [["S","h","e","e","t","J","S"],[1,2,3,4,5,6,7],[],[2,3,4,5,6,7,8]]; | ||||
| 		var _ws = X.utils.aoa_to_sheet(_data); | ||||
| 		var json = X.utils.sheet_to_json(_ws); | ||||
| 		assert.equal(json[0].__rowNum__, 1); | ||||
| 		assert.equal(json[1].__rowNum__, 3); | ||||
| 	}); | ||||
| 	it('should handle blankrows', function() { | ||||
| 		var _data = [["S","h","e","e","t","J","S"],[1,2,3,4,5,6,7],[],[2,3,4,5,6,7,8]]; | ||||
| 		var _ws = X.utils.aoa_to_sheet(_data); | ||||
| 		var json1 = X.utils.sheet_to_json(_ws); | ||||
| 		var json2 = X.utils.sheet_to_json(_ws, {header:1}); | ||||
| 		var json3 = X.utils.sheet_to_json(_ws, {blankrows:true}); | ||||
| 		var json4 = X.utils.sheet_to_json(_ws, {blankrows:true, header:1}); | ||||
| 		var json5 = X.utils.sheet_to_json(_ws, {blankrows:false}); | ||||
| 		var json6 = X.utils.sheet_to_json(_ws, {blankrows:false, header:1}); | ||||
| 		assert.equal(json1.length, 2); // = 2 non-empty records
 | ||||
| 		assert.equal(json2.length, 4); // = 4 sheet rows
 | ||||
| 		assert.equal(json3.length, 3); // = 2 records + 1 blank row
 | ||||
| 		assert.equal(json4.length, 4); // = 4 sheet rows
 | ||||
| 		assert.equal(json5.length, 2); // = 2 records
 | ||||
| 		assert.equal(json6.length, 3); // = 4 sheet rows - 1 blank row
 | ||||
| 	}); | ||||
| }); | ||||
| 
 | ||||
| describe('csv output', function() { | ||||
| 	var data, ws; | ||||
| 	var bef = (function() { | ||||
| 		data = [ | ||||
| 			[1,2,3,null], | ||||
| 			[true, false, null, "sheetjs"], | ||||
| 			["foo", "bar", new Date("2014-02-19T14:30Z"), "0.3"], | ||||
| 			[null, null, null], | ||||
| 			["baz", undefined, "qux"] | ||||
| 		]; | ||||
| 		ws = X.utils.aoa_to_sheet(data); | ||||
| 	}); | ||||
| 	if(typeof before != 'undefined') before(bef); | ||||
| 	else it('before', bef); | ||||
| 	it('should generate csv', function() { | ||||
| 		var baseline = "1,2,3,\nTRUE,FALSE,,sheetjs\nfoo,bar,2/19/14,0.3\n,,,\nbaz,,qux,\n"; | ||||
| 		assert.equal(baseline, X.utils.sheet_to_csv(ws)); | ||||
| 	}); | ||||
| 	it('should handle FS', function() { | ||||
| 		assert.equal(X.utils.sheet_to_csv(ws, {FS:"|"}).replace(/[|]/g,","), X.utils.sheet_to_csv(ws)); | ||||
| 		assert.equal(X.utils.sheet_to_csv(ws, {FS:";"}).replace(/[;]/g,","), X.utils.sheet_to_csv(ws)); | ||||
| 	}); | ||||
| 	it('should handle RS', function() { | ||||
| 		assert.equal(X.utils.sheet_to_csv(ws, {RS:"|"}).replace(/[|]/g,"\n"), X.utils.sheet_to_csv(ws)); | ||||
| 		assert.equal(X.utils.sheet_to_csv(ws, {RS:";"}).replace(/[;]/g,"\n"), X.utils.sheet_to_csv(ws)); | ||||
| 	}); | ||||
| 	it('should handle dateNF', function() { | ||||
| 		var baseline = "1,2,3,\nTRUE,FALSE,,sheetjs\nfoo,bar,20140219,0.3\n,,,\nbaz,,qux,\n"; | ||||
| 		var _ws =  X.utils.aoa_to_sheet(data, {cellDates:true}); | ||||
| 		delete _ws.C3.w; | ||||
| 		delete _ws.C3.z; | ||||
| 		assert.equal(baseline, X.utils.sheet_to_csv(_ws, {dateNF:"YYYYMMDD"})); | ||||
| 	}); | ||||
| 	it('should handle strip', function() { | ||||
| 		var baseline = "1,2,3\nTRUE,FALSE,,sheetjs\nfoo,bar,2/19/14,0.3\n\nbaz,,qux\n"; | ||||
| 		assert.equal(baseline, X.utils.sheet_to_csv(ws, {strip:true})); | ||||
| 	}); | ||||
| 	it('should handle blankrows', function() { | ||||
| 		var baseline = "1,2,3,\nTRUE,FALSE,,sheetjs\nfoo,bar,2/19/14,0.3\nbaz,,qux,\n"; | ||||
| 		assert.equal(baseline, X.utils.sheet_to_csv(ws, {blankrows:false})); | ||||
| 	}); | ||||
| }); | ||||
| 
 | ||||
| describe('js -> file -> js', function() { | ||||
| @ -1192,7 +1227,7 @@ describe('js -> file -> js', function() { | ||||
| 			["foo","bar",new Date("2014-02-19T14:30Z"), "0.3"], | ||||
| 			["baz", 6.9, "qux"] | ||||
| 		]; | ||||
| 		ws = sheet_from_array_of_arrays(data); | ||||
| 		ws = X.utils.aoa_to_sheet(data); | ||||
| 		wb = { SheetNames: ['Sheet1'], Sheets: {Sheet1: ws} }; | ||||
| 	}); | ||||
| 	if(typeof before != 'undefined') before(bef); | ||||
| @ -1234,7 +1269,7 @@ describe('corner cases', function() { | ||||
| 			["foo","bar",new Date("2014-02-19T14:30Z"), "0.3"], | ||||
| 			["baz", null, "q\"ux"] | ||||
| 		]; | ||||
| 		var ws = sheet_from_array_of_arrays(data); | ||||
| 		var ws = X.utils.aoa_to_sheet(data); | ||||
| 		ws.A1.f = ""; ws.A1.w = ""; | ||||
| 		delete ws.C3.w; delete ws.C3.z; ws.C3.XF = {ifmt:14}; | ||||
| 		ws.A4.t = "e"; | ||||
|  | ||||
							
								
								
									
										125
									
								
								xlsx.flow.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										125
									
								
								xlsx.flow.js
									
									
									
									
									
								
							| @ -444,7 +444,7 @@ function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string | ||||
| 	if(fmt.charCodeAt(fmt.length - 1) === 44) return write_num_cm(type, fmt, val); | ||||
| 	if(fmt.indexOf('%') !== -1) return write_num_pct(type, fmt, val); | ||||
| 	if(fmt.indexOf('E') !== -1) return write_num_exp(fmt, val); | ||||
| 	if(fmt.charCodeAt(0) === 36) return "$"+write_num_flt(type,fmt.substr(fmt[1]==' '?2:1),val); | ||||
| 	if(fmt.charCodeAt(0) === 36) return "$"+write_num_flt(type,fmt.substr(fmt.charAt(1)==' '?2:1),val); | ||||
| 	var o; | ||||
| 	var r/*:?Array<string>*/, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : ""; | ||||
| 	if(fmt.match(/^00+$/)) return sign + pad0r(aval,fmt.length); | ||||
| @ -470,7 +470,7 @@ function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string | ||||
| 	if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) { | ||||
| 		o = _strrev(write_num_flt(type, fmt.replace(/[\\-]/g,""), val)); | ||||
| 		ri = 0; | ||||
| 		return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o[ri++]:x==='0'?'0':"";})); | ||||
| 		return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o.charAt(ri++):x==='0'?'0':"";})); | ||||
| 	} | ||||
| 	if(fmt.match(phone)) { | ||||
| 		o = write_num_flt(type, "##########", val); | ||||
| @ -482,7 +482,7 @@ function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string | ||||
| 		ff = frac(aval, Math.pow(10,ri)-1, false); | ||||
| 		o = "" + sign; | ||||
| 		oa = write_num("n", /*::String(*/r[1]/*::)*/, ff[1]); | ||||
| 		if(oa[oa.length-1] == " ") oa = oa.substr(0,oa.length-1) + "0"; | ||||
| 		if(oa.charAt(oa.length-1) == " ") oa = oa.substr(0,oa.length-1) + "0"; | ||||
| 		o += oa + /*::String(*/r[2]/*::)*/ + "/" + /*::String(*/r[3]/*::)*/; | ||||
| 		oa = rpad_(ff[2],ri); | ||||
| 		if(oa.length < r[4].length) oa = hashq(r[4].substr(r[4].length-oa.length)) + oa; | ||||
| @ -553,7 +553,7 @@ function write_num_int(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string | ||||
| 	if(fmt.charCodeAt(fmt.length - 1) === 44) return write_num_cm2(type, fmt, val); | ||||
| 	if(fmt.indexOf('%') !== -1) return write_num_pct2(type, fmt, val); | ||||
| 	if(fmt.indexOf('E') !== -1) return write_num_exp2(fmt, val); | ||||
| 	if(fmt.charCodeAt(0) === 36) return "$"+write_num_int(type,fmt.substr(fmt[1]==' '?2:1),val); | ||||
| 	if(fmt.charCodeAt(0) === 36) return "$"+write_num_int(type,fmt.substr(fmt.charAt(1)==' '?2:1),val); | ||||
| 	var o; | ||||
| 	var r, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : ""; | ||||
| 	if(fmt.match(/^00+$/)) return sign + pad0(aval,fmt.length); | ||||
| @ -583,7 +583,7 @@ function write_num_int(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string | ||||
| 	if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) { | ||||
| 		o = _strrev(write_num_int(type, fmt.replace(/[\\-]/g,""), val)); | ||||
| 		ri = 0; | ||||
| 		return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o[ri++]:x==='0'?'0':"";})); | ||||
| 		return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o.charAt(ri++):x==='0'?'0':"";})); | ||||
| 	} | ||||
| 	if(fmt.match(phone)) { | ||||
| 		o = write_num_int(type, "##########", val); | ||||
| @ -595,7 +595,7 @@ function write_num_int(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string | ||||
| 		ff = frac(aval, Math.pow(10,ri)-1, false); | ||||
| 		o = "" + sign; | ||||
| 		oa = write_num("n", r[1], ff[1]); | ||||
| 		if(oa[oa.length-1] == " ") oa = oa.substr(0,oa.length-1) + "0"; | ||||
| 		if(oa.charAt(oa.length-1) == " ") oa = oa.substr(0,oa.length-1) + "0"; | ||||
| 		o += oa + r[2] + "/" + r[3]; | ||||
| 		oa = rpad_(ff[2],ri); | ||||
| 		if(oa.length < r[4].length) oa = hashq(r[4].substr(r[4].length-oa.length)) + oa; | ||||
| @ -847,7 +847,7 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) { | ||||
| 				j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")-1:out[i].v.length-1; | ||||
| 				vv = out[i].v.substr(j+1); | ||||
| 				for(; j>=0; --j) { | ||||
| 					if(jj>=0 && (out[i].v[j] === "0" || out[i].v[j] === "#")) vv = ostr[jj--] + vv; | ||||
| 					if(jj>=0 && (out[i].v.charAt(j) === "0" || out[i].v.charAt(j) === "#")) vv = ostr.charAt(jj--) + vv; | ||||
| 				} | ||||
| 				out[i].v = vv; | ||||
| 				out[i].t = 't'; | ||||
| @ -860,7 +860,7 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) { | ||||
| 				j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")+1:0; | ||||
| 				vv = out[i].v.substr(0,j); | ||||
| 				for(; j<out[i].v.length; ++j) { | ||||
| 					if(jj<ostr.length) vv += ostr[jj++]; | ||||
| 					if(jj<ostr.length) vv += ostr.charAt(jj++); | ||||
| 				} | ||||
| 				out[i].v = vv; | ||||
| 				out[i].t = 't'; | ||||
| @ -1401,6 +1401,18 @@ function datenum(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ { | ||||
| 	if(date1904) epoch += 1462*24*60*60*1000; | ||||
| 	return (epoch + 2209161600000) / (24 * 60 * 60 * 1000); | ||||
| } | ||||
| function numdate(v/*:number*/)/*:Date*/ { | ||||
| 	var date = SSF.parse_date_code(v); | ||||
| 	var val = new Date(); | ||||
| 	if(date == null) throw new Error("Bad Date Code: " + v); | ||||
| 	val.setUTCDate(date.d); | ||||
| 	val.setUTCMonth(date.m-1); | ||||
| 	val.setUTCFullYear(date.y); | ||||
| 	val.setUTCHours(date.H); | ||||
| 	val.setUTCMinutes(date.M); | ||||
| 	val.setUTCSeconds(date.S); | ||||
| 	return val; | ||||
| } | ||||
| 
 | ||||
| /* ISO 8601 Duration */ | ||||
| function parse_isodur(s) { | ||||
| @ -2049,6 +2061,42 @@ var make_offcrypto = function(O, _crypto) { | ||||
| /*:: declare var crypto:any; */ | ||||
| make_offcrypto(OFFCRYPTO, typeof crypto !== "undefined" ? crypto : undefined); | ||||
| 
 | ||||
| function sheet_to_workbook(sheet/*:Worksheet*/, opts)/*:Workbook*/ { | ||||
| 	var n = opts && opts.sheet ? opts.sheet : "Sheet1"; | ||||
| 	var sheets = {}; sheets[n] = sheet; | ||||
| 	return { SheetNames: [n], Sheets: sheets }; | ||||
| } | ||||
| 
 | ||||
| function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ { | ||||
| 	var o = opts || {}; | ||||
| 	var ws/*:Worksheet*/ = ({}/*:any*/); | ||||
| 	var range/*:Range*/ = ({s: {c:10000000, r:10000000}, e: {c:0, r:0}}/*:any*/); | ||||
| 	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(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 cell_ref = encode_cell(({c:C,r:R}/*:any*/)); | ||||
| 			if(cell.v === null) { if(!o.cellStubs) continue; cell.t = 'z'; } | ||||
| 			else if(typeof cell.v === 'number') cell.t = 'n'; | ||||
| 			else if(typeof cell.v === 'boolean') cell.t = 'b'; | ||||
| 			else if(cell.v instanceof Date) { | ||||
| 				cell.z = o.dateNF || SSF._table[14]; | ||||
| 				if(o.cellDates) cell.t = 'd'; | ||||
| 				else { cell.t = 'n'; cell.v = datenum(cell.v); } | ||||
| 				cell.w = SSF.format(cell.z, cell.v); | ||||
| 			} | ||||
| 			else cell.t = 's'; | ||||
| 			ws[cell_ref] = cell; | ||||
| 		} | ||||
| 	} | ||||
| 	if(range.s.c < 10000000) ws['!ref'] = encode_range(range); | ||||
| 	return ws; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* [MS-XLSB] 2.5.143 */ | ||||
| function parse_StrRun(data, length/*:?number*/) { | ||||
| @ -5389,7 +5437,7 @@ function parse_numFmts(t, styles, opts) { | ||||
| 
 | ||||
| function write_numFmts(NF/*:{[n:number]:string}*/, opts) { | ||||
| 	var o = ["<numFmts>"]; | ||||
| 	[[5,8],[23,26],[41,44],[63,66],[164,392]].forEach(function(r) { | ||||
| 	[[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) { | ||||
| 		for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) o[o.length] = (writextag('numFmt',null,{numFmtId:i,formatCode:escapexml(NF[i])})); | ||||
| 	}); | ||||
| 	if(o.length === 1) return ""; | ||||
| @ -7029,18 +7077,18 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks, | ||||
| 			/* 2.5.198.31 TODO */ | ||||
| 			case 'PtgAreaN': | ||||
| 				type = f[1][0]; r = shift_range_xls(f[1][1], _range, opts); | ||||
| 				stack.push(encode_range_xls(r, opts)); | ||||
| 				stack.push(encode_range_xls((r/*:any*/), opts)); | ||||
| 				break; | ||||
| 			/* 2.5.198.27 TODO: fixed points */ | ||||
| 			case 'PtgArea': | ||||
| 				type = f[1][0]; r = shift_range_xls(f[1][1], _range, opts); | ||||
| 				stack.push(encode_range_xls(r, opts)); | ||||
| 				stack.push(encode_range_xls((r/*:any*/), opts)); | ||||
| 				break; | ||||
| 			/* 2.5.198.28 */ | ||||
| 			case 'PtgArea3d': // TODO: lots of stuff
 | ||||
| 				type = f[1][0]; ixti = /*::Number(*/f[1][1]/*::)*/; r = f[1][2]; | ||||
| 				sname = (supbooks && supbooks[1] ? supbooks[1][ixti+1] : "**MISSING**"); | ||||
| 				stack.push(sname + "!" + encode_range(r)); | ||||
| 				stack.push(sname + "!" + encode_range((r/*:any*/))); | ||||
| 				break; | ||||
| 			/* 2.5.198.41 */ | ||||
| 			case 'PtgAttrSum': | ||||
| @ -10225,6 +10273,7 @@ function xlml_normalize(d)/*:string*/ { | ||||
| var xlmlregex = /<(\/?)([^\s?>!\/:]*:|)([^\s?>]*[^\s?>\/])[^>]*>/mg; | ||||
| //var xlmlregex = /<(\/?)([a-z0-9]*:|)(\w+)[^>]*>/mg;
 | ||||
| function parse_xlml_xml(d, opts)/*:Workbook*/ { | ||||
| 	make_ssf(SSF); | ||||
| 	var str = debom(xlml_normalize(d)); | ||||
| 	if(opts && opts.type == 'binary' && typeof cptable !== 'undefined') str = cptable.utils.decode(65001, char_codes(str)); | ||||
| 	if(str.substr(0,1000).indexOf("<html") >= 0) return parse_html(str, opts); | ||||
| @ -10335,7 +10384,10 @@ function parse_xlml_xml(d, opts)/*:Workbook*/ { | ||||
| 			break; | ||||
| 
 | ||||
| 		case 'NumberFormat': | ||||
| 			stag.nf = xlml_parsexmltag(Rn[0]).Format || "General"; | ||||
| 			stag.nf = unescapexml(xlml_parsexmltag(Rn[0]).Format || "General"); | ||||
| 			if(XLMLFormatMap[stag.nf]) stag.nf = XLMLFormatMap[stag.nf]; | ||||
| 			for(var ssfidx = 0; ssfidx != 0x188; ++ssfidx) if(SSF._table[ssfidx] == stag.nf) break; | ||||
| 			if(ssfidx == 0x188) for(ssfidx = 0x39; ssfidx != 0x188; ++ssfidx) if(SSF._table[ssfidx] == null) { SSF.load(stag.nf, ssfidx); break; } | ||||
| 			break; | ||||
| 
 | ||||
| 		case 'Column': | ||||
| @ -11012,7 +11064,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 	var out = {}; | ||||
| 	var Directory = {}; | ||||
| 	var found_sheet = false; | ||||
| 	var range = {}; | ||||
| 	var range/*:Range*/ = ({}/*:any*/); | ||||
| 	var last_formula = null; | ||||
| 	var sst = []; | ||||
| 	var cur_sheet = ""; | ||||
| @ -13977,9 +14029,7 @@ function writeSync(wb/*:Workbook*/, opts/*:?WriteOpts*/) { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| function writeFileSync(wb/*:Workbook*/, filename/*:string*/, opts/*:?WriteFileOpts*/) { | ||||
| 	var o = opts||{}; o.type = 'file'; | ||||
| 	o.file = filename; | ||||
| function resolve_book_type(o/*?WriteFileOpts*/) { | ||||
| 	if(!o.bookType) switch(o.file.slice(-5).toLowerCase()) { | ||||
| 		case '.xlsx': o.bookType = 'xlsx'; break; | ||||
| 		case '.xlsm': o.bookType = 'xlsm'; break; | ||||
| @ -13992,9 +14042,23 @@ function writeFileSync(wb/*:Workbook*/, filename/*:string*/, opts/*:?WriteFileOp | ||||
| 		case '.ods': o.bookType = 'ods'; break; | ||||
| 		case '.csv': o.bookType = 'csv'; break; | ||||
| 	}} | ||||
| } | ||||
| 
 | ||||
| function writeFileSync(wb/*:Workbook*/, filename/*:string*/, opts/*:?WriteFileOpts*/) { | ||||
| 	var o = opts||{}; o.type = 'file'; | ||||
| 	o.file = filename; | ||||
| 	resolve_book_type(o); | ||||
| 	return writeSync(wb, o); | ||||
| } | ||||
| 
 | ||||
| function writeFileAsync(filename/*:string*/, wb/*:Workbook*/, opts/*:?WriteFileOpts*/, cb/*:?(e?:ErrnoError)=>void*/) { | ||||
| 	var o = opts||{}; o.type = 'file'; | ||||
| 	o.file = filename; | ||||
| 	resolve_book_type(o); | ||||
| 	o.type = 'buffer'; | ||||
| 	var _cb = cb; if(!(_cb instanceof Function)) _cb = (opts/*:any*/); | ||||
| 	return _fs.writeFile(filename, writeSync(wb, o), _cb); | ||||
| } | ||||
| function decode_row(rowstr/*:string*/)/*:number*/ { return parseInt(unfix_row(rowstr),10) - 1; } | ||||
| function encode_row(row/*:number*/)/*:string*/ { return "" + (row + 1); } | ||||
| function fix_row(cstr/*:string*/)/*:string*/ { return cstr.replace(/([A-Z]|^)(\d+)$/,"$1$$$2"); } | ||||
| @ -14011,7 +14075,8 @@ function encode_cell(cell/*:CellAddress*/)/*:string*/ { return encode_col(cell.c | ||||
| function fix_cell(cstr/*:string*/)/*:string*/ { return fix_col(fix_row(cstr)); } | ||||
| function unfix_cell(cstr/*:string*/)/*:string*/ { return unfix_col(unfix_row(cstr)); } | ||||
| function decode_range(range/*:string*/)/*:Range*/ { var x =range.split(":").map(decode_cell); return {s:x[0],e:x[x.length-1]}; } | ||||
| function encode_range(cs/*:any*/,ce/*:?any*/)/*:string*/ { | ||||
| /*# if only one arg, it is assumed to be a Range.  If 2 args, both are cell addresses */ | ||||
| function encode_range(cs/*:CellAddrSpec|Range*/,ce/*:?CellAddrSpec*/)/*:string*/ { | ||||
| 	if(typeof ce === 'undefined' || typeof ce === 'number') { | ||||
| /*:: if(!(cs instanceof Range)) throw "unreachable"; */ | ||||
| 		return encode_range(cs.s, cs.e); | ||||
| @ -14066,8 +14131,8 @@ function format_cell(cell/*:Cell*/, v/*:any*/, o/*:any*/) { | ||||
| 	if(cell == null || cell.t == null || cell.t == 'z') return ""; | ||||
| 	if(cell.w !== undefined) return cell.w; | ||||
| 	if(cell.t == 'd' && !cell.z && o && o.dateNF) cell.z = o.dateNF; | ||||
| 	if(v == undefined) return safe_format_cell(cell, cell.v); | ||||
| 	return safe_format_cell(cell, v); | ||||
| 	if(v == undefined) return safe_format_cell(cell, cell.v, o); | ||||
| 	return safe_format_cell(cell, v, o); | ||||
| } | ||||
| 
 | ||||
| function sheet_to_json(sheet/*:Worksheet*/, opts/*:?Sheet2JSONOpts*/){ | ||||
| @ -14099,7 +14164,7 @@ function sheet_to_json(sheet/*:Worksheet*/, opts/*:?Sheet2JSONOpts*/){ | ||||
| 			case 3: hdr[C] = o.header[C - r.s.c]; break; | ||||
| 			default: | ||||
| 				if(val == null) continue; | ||||
| 				vv = v = format_cell(val); | ||||
| 				vv = v = format_cell(val, null, o); | ||||
| 				var counter = 0; | ||||
| 				for(var CC = 0; CC < hdr.length; ++CC) if(hdr[CC] == vv) vv = v + "_" + (++counter); | ||||
| 				hdr[C] = vv; | ||||
| @ -14135,19 +14200,17 @@ function sheet_to_json(sheet/*:Worksheet*/, opts/*:?Sheet2JSONOpts*/){ | ||||
| 					else if(raw && v === null) row[hdr[C]] = null; | ||||
| 					else continue; | ||||
| 				} else { | ||||
| 					row[hdr[C]] = raw ? v : format_cell(val,v); | ||||
| 					row[hdr[C]] = raw ? v : format_cell(val,v,o); | ||||
| 				} | ||||
| 				isempty = false; | ||||
| 			} | ||||
| 		} | ||||
| 		if(isempty === false || header === 1) out[outi++] = row; | ||||
| 		if((isempty === false) || (header === 1 ? o.blankrows !== false : !!o.blankrows)) out[outi++] = row; | ||||
| 	} | ||||
| 	out.length = outi; | ||||
| 	return out; | ||||
| } | ||||
| 
 | ||||
| function sheet_to_row_object_array(sheet/*:Worksheet*/, opts/*:?Sheet2JSONOpts*/) { return sheet_to_json(sheet, opts != null ? opts : {}); } | ||||
| 
 | ||||
| function sheet_to_csv(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) { | ||||
| 	var out = "", txt = "", qreg = /"/g; | ||||
| 	var o = opts == null ? {} : opts; | ||||
| @ -14155,27 +14218,31 @@ function sheet_to_csv(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) { | ||||
| 	var r = safe_decode_range(sheet["!ref"]); | ||||
| 	var FS = o.FS !== undefined ? o.FS : ",", fs = FS.charCodeAt(0); | ||||
| 	var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0); | ||||
| 	var endregex = new RegExp(FS+"+$"); | ||||
| 	var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$"); | ||||
| 	var row = "", rr = "", cols = []; | ||||
| 	var i = 0, cc = 0, val; | ||||
| 	var R = 0, C = 0; | ||||
| 	for(C = r.s.c; C <= r.e.c; ++C) cols[C] = encode_col(C); | ||||
| 	for(R = r.s.r; R <= r.e.r; ++R) { | ||||
| 		var isempty = true; | ||||
| 		row = ""; | ||||
| 		rr = encode_row(R); | ||||
| 		for(C = r.s.c; C <= r.e.c; ++C) { | ||||
| 			val = sheet[cols[C] + rr]; | ||||
| 			if(val == null) txt = ""; | ||||
| 			else if(val.v != null) { | ||||
| 				txt = ''+format_cell(val); | ||||
| 				isempty = false; | ||||
| 				txt = ''+format_cell(val, null, o); | ||||
| 				for(i = 0, cc = 0; i !== txt.length; ++i) if((cc = txt.charCodeAt(i)) === fs || cc === rs || cc === 34) { | ||||
| 					txt = "\"" + txt.replace(qreg, '""') + "\""; break; } | ||||
| 			} else if(val.f != null && !val.F) { | ||||
| 				isempty = false; | ||||
| 				txt = '=' + val.f; if(txt.indexOf(",") >= 0) txt = '"' + txt.replace(qreg, '""') + '"'; | ||||
| 			} else txt = ""; | ||||
| 			/* NOTE: Excel CSV does not support array formulae */ | ||||
| 			row += (C === r.s.c ? "" : FS) + txt; | ||||
| 		} | ||||
| 		if(o.blankrows === false && isempty) continue; | ||||
| 		if(o.strip) row = row.replace(endregex,""); | ||||
| 		out += row + RS; | ||||
| 	} | ||||
| @ -14233,10 +14300,11 @@ var utils = { | ||||
| 	make_csv: sheet_to_csv, | ||||
| 	make_json: sheet_to_json, | ||||
| 	make_formulae: sheet_to_formulae, | ||||
| 	aoa_to_sheet: aoa_to_sheet, | ||||
| 	sheet_to_csv: sheet_to_csv, | ||||
| 	sheet_to_json: sheet_to_json, | ||||
| 	sheet_to_formulae: sheet_to_formulae, | ||||
| 	sheet_to_row_object_array: sheet_to_row_object_array | ||||
| 	sheet_to_row_object_array: sheet_to_json | ||||
| }; | ||||
| XLSX.parse_xlscfb = parse_xlscfb; | ||||
| XLSX.parse_ods = parse_ods; | ||||
| @ -14249,6 +14317,7 @@ XLSX.readFileSync = readFileSync; | ||||
| XLSX.write = writeSync; | ||||
| XLSX.writeFile = writeFileSync; | ||||
| XLSX.writeFileSync = writeFileSync; | ||||
| XLSX.writeFileAsync = writeFileAsync; | ||||
| XLSX.utils = utils; | ||||
| XLSX.CFB = CFB; | ||||
| XLSX.SSF = SSF; | ||||
|  | ||||
							
								
								
									
										122
									
								
								xlsx.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										122
									
								
								xlsx.js
									
									
									
									
									
								
							| @ -425,7 +425,7 @@ function write_num_flt(type, fmt, val) { | ||||
| 	if(fmt.charCodeAt(fmt.length - 1) === 44) return write_num_cm(type, fmt, val); | ||||
| 	if(fmt.indexOf('%') !== -1) return write_num_pct(type, fmt, val); | ||||
| 	if(fmt.indexOf('E') !== -1) return write_num_exp(fmt, val); | ||||
| 	if(fmt.charCodeAt(0) === 36) return "$"+write_num_flt(type,fmt.substr(fmt[1]==' '?2:1),val); | ||||
| 	if(fmt.charCodeAt(0) === 36) return "$"+write_num_flt(type,fmt.substr(fmt.charAt(1)==' '?2:1),val); | ||||
| 	var o; | ||||
| 	var r, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : ""; | ||||
| 	if(fmt.match(/^00+$/)) return sign + pad0r(aval,fmt.length); | ||||
| @ -451,7 +451,7 @@ function write_num_flt(type, fmt, val) { | ||||
| 	if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) { | ||||
| 		o = _strrev(write_num_flt(type, fmt.replace(/[\\-]/g,""), val)); | ||||
| 		ri = 0; | ||||
| 		return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o[ri++]:x==='0'?'0':"";})); | ||||
| 		return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o.charAt(ri++):x==='0'?'0':"";})); | ||||
| 	} | ||||
| 	if(fmt.match(phone)) { | ||||
| 		o = write_num_flt(type, "##########", val); | ||||
| @ -463,7 +463,7 @@ function write_num_flt(type, fmt, val) { | ||||
| 		ff = frac(aval, Math.pow(10,ri)-1, false); | ||||
| 		o = "" + sign; | ||||
| 		oa = write_num("n", r[1], ff[1]); | ||||
| 		if(oa[oa.length-1] == " ") oa = oa.substr(0,oa.length-1) + "0"; | ||||
| 		if(oa.charAt(oa.length-1) == " ") oa = oa.substr(0,oa.length-1) + "0"; | ||||
| 		o += oa + r[2] + "/" + r[3]; | ||||
| 		oa = rpad_(ff[2],ri); | ||||
| 		if(oa.length < r[4].length) oa = hashq(r[4].substr(r[4].length-oa.length)) + oa; | ||||
| @ -534,7 +534,7 @@ function write_num_int(type, fmt, val) { | ||||
| 	if(fmt.charCodeAt(fmt.length - 1) === 44) return write_num_cm2(type, fmt, val); | ||||
| 	if(fmt.indexOf('%') !== -1) return write_num_pct2(type, fmt, val); | ||||
| 	if(fmt.indexOf('E') !== -1) return write_num_exp2(fmt, val); | ||||
| 	if(fmt.charCodeAt(0) === 36) return "$"+write_num_int(type,fmt.substr(fmt[1]==' '?2:1),val); | ||||
| 	if(fmt.charCodeAt(0) === 36) return "$"+write_num_int(type,fmt.substr(fmt.charAt(1)==' '?2:1),val); | ||||
| 	var o; | ||||
| 	var r, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : ""; | ||||
| 	if(fmt.match(/^00+$/)) return sign + pad0(aval,fmt.length); | ||||
| @ -562,7 +562,7 @@ return "." + $1 + fill("0", r[1].length-$1.length); }); | ||||
| 	if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) { | ||||
| 		o = _strrev(write_num_int(type, fmt.replace(/[\\-]/g,""), val)); | ||||
| 		ri = 0; | ||||
| 		return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o[ri++]:x==='0'?'0':"";})); | ||||
| 		return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o.charAt(ri++):x==='0'?'0':"";})); | ||||
| 	} | ||||
| 	if(fmt.match(phone)) { | ||||
| 		o = write_num_int(type, "##########", val); | ||||
| @ -574,7 +574,7 @@ return "." + $1 + fill("0", r[1].length-$1.length); }); | ||||
| 		ff = frac(aval, Math.pow(10,ri)-1, false); | ||||
| 		o = "" + sign; | ||||
| 		oa = write_num("n", r[1], ff[1]); | ||||
| 		if(oa[oa.length-1] == " ") oa = oa.substr(0,oa.length-1) + "0"; | ||||
| 		if(oa.charAt(oa.length-1) == " ") oa = oa.substr(0,oa.length-1) + "0"; | ||||
| 		o += oa + r[2] + "/" + r[3]; | ||||
| 		oa = rpad_(ff[2],ri); | ||||
| 		if(oa.length < r[4].length) oa = hashq(r[4].substr(r[4].length-oa.length)) + oa; | ||||
| @ -823,7 +823,7 @@ out[i].v = write_date(out[i].t.charCodeAt(0), out[i].v, dt, ss0); | ||||
| 				j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")-1:out[i].v.length-1; | ||||
| 				vv = out[i].v.substr(j+1); | ||||
| 				for(; j>=0; --j) { | ||||
| 					if(jj>=0 && (out[i].v[j] === "0" || out[i].v[j] === "#")) vv = ostr[jj--] + vv; | ||||
| 					if(jj>=0 && (out[i].v.charAt(j) === "0" || out[i].v.charAt(j) === "#")) vv = ostr.charAt(jj--) + vv; | ||||
| 				} | ||||
| 				out[i].v = vv; | ||||
| 				out[i].t = 't'; | ||||
| @ -836,7 +836,7 @@ out[i].v = write_date(out[i].t.charCodeAt(0), out[i].v, dt, ss0); | ||||
| 				j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")+1:0; | ||||
| 				vv = out[i].v.substr(0,j); | ||||
| 				for(; j<out[i].v.length; ++j) { | ||||
| 					if(jj<ostr.length) vv += ostr[jj++]; | ||||
| 					if(jj<ostr.length) vv += ostr.charAt(jj++); | ||||
| 				} | ||||
| 				out[i].v = vv; | ||||
| 				out[i].t = 't'; | ||||
| @ -1353,6 +1353,18 @@ function datenum(v, date1904) { | ||||
| 	if(date1904) epoch += 1462*24*60*60*1000; | ||||
| 	return (epoch + 2209161600000) / (24 * 60 * 60 * 1000); | ||||
| } | ||||
| function numdate(v) { | ||||
| 	var date = SSF.parse_date_code(v); | ||||
| 	var val = new Date(); | ||||
| 	if(date == null) throw new Error("Bad Date Code: " + v); | ||||
| 	val.setUTCDate(date.d); | ||||
| 	val.setUTCMonth(date.m-1); | ||||
| 	val.setUTCFullYear(date.y); | ||||
| 	val.setUTCHours(date.H); | ||||
| 	val.setUTCMinutes(date.M); | ||||
| 	val.setUTCSeconds(date.S); | ||||
| 	return val; | ||||
| } | ||||
| 
 | ||||
| /* ISO 8601 Duration */ | ||||
| function parse_isodur(s) { | ||||
| @ -1997,6 +2009,42 @@ var make_offcrypto = function(O, _crypto) { | ||||
| }; | ||||
| make_offcrypto(OFFCRYPTO, typeof crypto !== "undefined" ? crypto : undefined); | ||||
| 
 | ||||
| function sheet_to_workbook(sheet, opts) { | ||||
| 	var n = opts && opts.sheet ? opts.sheet : "Sheet1"; | ||||
| 	var sheets = {}; sheets[n] = sheet; | ||||
| 	return { SheetNames: [n], Sheets: sheets }; | ||||
| } | ||||
| 
 | ||||
| function aoa_to_sheet(data, opts) { | ||||
| 	var o = opts || {}; | ||||
| 	var ws = ({}); | ||||
| 	var range = ({s: {c:10000000, r:10000000}, e: {c:0, r:0}}); | ||||
| 	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(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 cell_ref = encode_cell(({c:C,r:R})); | ||||
| 			if(cell.v === null) { if(!o.cellStubs) continue; cell.t = 'z'; } | ||||
| 			else if(typeof cell.v === 'number') cell.t = 'n'; | ||||
| 			else if(typeof cell.v === 'boolean') cell.t = 'b'; | ||||
| 			else if(cell.v instanceof Date) { | ||||
| 				cell.z = o.dateNF || SSF._table[14]; | ||||
| 				if(o.cellDates) cell.t = 'd'; | ||||
| 				else { cell.t = 'n'; cell.v = datenum(cell.v); } | ||||
| 				cell.w = SSF.format(cell.z, cell.v); | ||||
| 			} | ||||
| 			else cell.t = 's'; | ||||
| 			ws[cell_ref] = cell; | ||||
| 		} | ||||
| 	} | ||||
| 	if(range.s.c < 10000000) ws['!ref'] = encode_range(range); | ||||
| 	return ws; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* [MS-XLSB] 2.5.143 */ | ||||
| function parse_StrRun(data, length) { | ||||
| @ -5335,7 +5383,7 @@ function parse_numFmts(t, styles, opts) { | ||||
| 
 | ||||
| function write_numFmts(NF, opts) { | ||||
| 	var o = ["<numFmts>"]; | ||||
| 	[[5,8],[23,26],[41,44],[63,66],[164,392]].forEach(function(r) { | ||||
| 	[[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) { | ||||
| 		for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) o[o.length] = (writextag('numFmt',null,{numFmtId:i,formatCode:escapexml(NF[i])})); | ||||
| 	}); | ||||
| 	if(o.length === 1) return ""; | ||||
| @ -6974,18 +7022,18 @@ function stringify_formula(formula/*Array<any>*/, range, cell, supbooks, opts) { | ||||
| 			/* 2.5.198.31 TODO */ | ||||
| 			case 'PtgAreaN': | ||||
| 				type = f[1][0]; r = shift_range_xls(f[1][1], _range, opts); | ||||
| 				stack.push(encode_range_xls(r, opts)); | ||||
| 				stack.push(encode_range_xls((r), opts)); | ||||
| 				break; | ||||
| 			/* 2.5.198.27 TODO: fixed points */ | ||||
| 			case 'PtgArea': | ||||
| 				type = f[1][0]; r = shift_range_xls(f[1][1], _range, opts); | ||||
| 				stack.push(encode_range_xls(r, opts)); | ||||
| 				stack.push(encode_range_xls((r), opts)); | ||||
| 				break; | ||||
| 			/* 2.5.198.28 */ | ||||
| 			case 'PtgArea3d': // TODO: lots of stuff
 | ||||
| 				type = f[1][0]; ixti = f[1][1]; r = f[1][2]; | ||||
| 				sname = (supbooks && supbooks[1] ? supbooks[1][ixti+1] : "**MISSING**"); | ||||
| 				stack.push(sname + "!" + encode_range(r)); | ||||
| 				stack.push(sname + "!" + encode_range((r))); | ||||
| 				break; | ||||
| 			/* 2.5.198.41 */ | ||||
| 			case 'PtgAttrSum': | ||||
| @ -10168,6 +10216,7 @@ function xlml_normalize(d) { | ||||
| var xlmlregex = /<(\/?)([^\s?>!\/:]*:|)([^\s?>]*[^\s?>\/])[^>]*>/mg; | ||||
| //var xlmlregex = /<(\/?)([a-z0-9]*:|)(\w+)[^>]*>/mg;
 | ||||
| function parse_xlml_xml(d, opts) { | ||||
| 	make_ssf(SSF); | ||||
| 	var str = debom(xlml_normalize(d)); | ||||
| 	if(opts && opts.type == 'binary' && typeof cptable !== 'undefined') str = cptable.utils.decode(65001, char_codes(str)); | ||||
| 	if(str.substr(0,1000).indexOf("<html") >= 0) return parse_html(str, opts); | ||||
| @ -10277,7 +10326,10 @@ for(var cma = c; cma <= cc; ++cma) { | ||||
| 			break; | ||||
| 
 | ||||
| 		case 'NumberFormat': | ||||
| 			stag.nf = xlml_parsexmltag(Rn[0]).Format || "General"; | ||||
| 			stag.nf = unescapexml(xlml_parsexmltag(Rn[0]).Format || "General"); | ||||
| 			if(XLMLFormatMap[stag.nf]) stag.nf = XLMLFormatMap[stag.nf]; | ||||
| 			for(var ssfidx = 0; ssfidx != 0x188; ++ssfidx) if(SSF._table[ssfidx] == stag.nf) break; | ||||
| 			if(ssfidx == 0x188) for(ssfidx = 0x39; ssfidx != 0x188; ++ssfidx) if(SSF._table[ssfidx] == null) { SSF.load(stag.nf, ssfidx); break; } | ||||
| 			break; | ||||
| 
 | ||||
| 		case 'Column': | ||||
| @ -10953,7 +11005,7 @@ function parse_workbook(blob, options) { | ||||
| 	var out = {}; | ||||
| 	var Directory = {}; | ||||
| 	var found_sheet = false; | ||||
| 	var range = {}; | ||||
| 	var range = ({}); | ||||
| 	var last_formula = null; | ||||
| 	var sst = []; | ||||
| 	var cur_sheet = ""; | ||||
| @ -13914,9 +13966,7 @@ function writeSync(wb, opts) { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| function writeFileSync(wb, filename, opts) { | ||||
| 	var o = opts||{}; o.type = 'file'; | ||||
| 	o.file = filename; | ||||
| function resolve_book_type(o/*?WriteFileOpts*/) { | ||||
| 	if(!o.bookType) switch(o.file.slice(-5).toLowerCase()) { | ||||
| 		case '.xlsx': o.bookType = 'xlsx'; break; | ||||
| 		case '.xlsm': o.bookType = 'xlsm'; break; | ||||
| @ -13929,9 +13979,23 @@ function writeFileSync(wb, filename, opts) { | ||||
| 		case '.ods': o.bookType = 'ods'; break; | ||||
| 		case '.csv': o.bookType = 'csv'; break; | ||||
| 	}} | ||||
| } | ||||
| 
 | ||||
| function writeFileSync(wb, filename, opts) { | ||||
| 	var o = opts||{}; o.type = 'file'; | ||||
| 	o.file = filename; | ||||
| 	resolve_book_type(o); | ||||
| 	return writeSync(wb, o); | ||||
| } | ||||
| 
 | ||||
| function writeFileAsync(filename, wb, opts, cb) { | ||||
| 	var o = opts||{}; o.type = 'file'; | ||||
| 	o.file = filename; | ||||
| 	resolve_book_type(o); | ||||
| 	o.type = 'buffer'; | ||||
| 	var _cb = cb; if(!(_cb instanceof Function)) _cb = (opts); | ||||
| 	return _fs.writeFile(filename, writeSync(wb, o), _cb); | ||||
| } | ||||
| function decode_row(rowstr) { return parseInt(unfix_row(rowstr),10) - 1; } | ||||
| function encode_row(row) { return "" + (row + 1); } | ||||
| function fix_row(cstr) { return cstr.replace(/([A-Z]|^)(\d+)$/,"$1$$$2"); } | ||||
| @ -13999,8 +14063,8 @@ function format_cell(cell, v, o) { | ||||
| 	if(cell == null || cell.t == null || cell.t == 'z') return ""; | ||||
| 	if(cell.w !== undefined) return cell.w; | ||||
| 	if(cell.t == 'd' && !cell.z && o && o.dateNF) cell.z = o.dateNF; | ||||
| 	if(v == undefined) return safe_format_cell(cell, cell.v); | ||||
| 	return safe_format_cell(cell, v); | ||||
| 	if(v == undefined) return safe_format_cell(cell, cell.v, o); | ||||
| 	return safe_format_cell(cell, v, o); | ||||
| } | ||||
| 
 | ||||
| function sheet_to_json(sheet, opts){ | ||||
| @ -14032,7 +14096,7 @@ function sheet_to_json(sheet, opts){ | ||||
| 			case 3: hdr[C] = o.header[C - r.s.c]; break; | ||||
| 			default: | ||||
| 				if(val == null) continue; | ||||
| 				vv = v = format_cell(val); | ||||
| 				vv = v = format_cell(val, null, o); | ||||
| 				var counter = 0; | ||||
| 				for(var CC = 0; CC < hdr.length; ++CC) if(hdr[CC] == vv) vv = v + "_" + (++counter); | ||||
| 				hdr[C] = vv; | ||||
| @ -14068,19 +14132,17 @@ function sheet_to_json(sheet, opts){ | ||||
| 					else if(raw && v === null) row[hdr[C]] = null; | ||||
| 					else continue; | ||||
| 				} else { | ||||
| 					row[hdr[C]] = raw ? v : format_cell(val,v); | ||||
| 					row[hdr[C]] = raw ? v : format_cell(val,v,o); | ||||
| 				} | ||||
| 				isempty = false; | ||||
| 			} | ||||
| 		} | ||||
| 		if(isempty === false || header === 1) out[outi++] = row; | ||||
| 		if((isempty === false) || (header === 1 ? o.blankrows !== false : !!o.blankrows)) out[outi++] = row; | ||||
| 	} | ||||
| 	out.length = outi; | ||||
| 	return out; | ||||
| } | ||||
| 
 | ||||
| function sheet_to_row_object_array(sheet, opts) { return sheet_to_json(sheet, opts != null ? opts : {}); } | ||||
| 
 | ||||
| function sheet_to_csv(sheet, opts) { | ||||
| 	var out = "", txt = "", qreg = /"/g; | ||||
| 	var o = opts == null ? {} : opts; | ||||
| @ -14088,27 +14150,31 @@ function sheet_to_csv(sheet, opts) { | ||||
| 	var r = safe_decode_range(sheet["!ref"]); | ||||
| 	var FS = o.FS !== undefined ? o.FS : ",", fs = FS.charCodeAt(0); | ||||
| 	var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0); | ||||
| 	var endregex = new RegExp(FS+"+$"); | ||||
| 	var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$"); | ||||
| 	var row = "", rr = "", cols = []; | ||||
| 	var i = 0, cc = 0, val; | ||||
| 	var R = 0, C = 0; | ||||
| 	for(C = r.s.c; C <= r.e.c; ++C) cols[C] = encode_col(C); | ||||
| 	for(R = r.s.r; R <= r.e.r; ++R) { | ||||
| 		var isempty = true; | ||||
| 		row = ""; | ||||
| 		rr = encode_row(R); | ||||
| 		for(C = r.s.c; C <= r.e.c; ++C) { | ||||
| 			val = sheet[cols[C] + rr]; | ||||
| 			if(val == null) txt = ""; | ||||
| 			else if(val.v != null) { | ||||
| 				txt = ''+format_cell(val); | ||||
| 				isempty = false; | ||||
| 				txt = ''+format_cell(val, null, o); | ||||
| 				for(i = 0, cc = 0; i !== txt.length; ++i) if((cc = txt.charCodeAt(i)) === fs || cc === rs || cc === 34) { | ||||
| 					txt = "\"" + txt.replace(qreg, '""') + "\""; break; } | ||||
| 			} else if(val.f != null && !val.F) { | ||||
| 				isempty = false; | ||||
| 				txt = '=' + val.f; if(txt.indexOf(",") >= 0) txt = '"' + txt.replace(qreg, '""') + '"'; | ||||
| 			} else txt = ""; | ||||
| 			/* NOTE: Excel CSV does not support array formulae */ | ||||
| 			row += (C === r.s.c ? "" : FS) + txt; | ||||
| 		} | ||||
| 		if(o.blankrows === false && isempty) continue; | ||||
| 		if(o.strip) row = row.replace(endregex,""); | ||||
| 		out += row + RS; | ||||
| 	} | ||||
| @ -14166,10 +14232,11 @@ var utils = { | ||||
| 	make_csv: sheet_to_csv, | ||||
| 	make_json: sheet_to_json, | ||||
| 	make_formulae: sheet_to_formulae, | ||||
| 	aoa_to_sheet: aoa_to_sheet, | ||||
| 	sheet_to_csv: sheet_to_csv, | ||||
| 	sheet_to_json: sheet_to_json, | ||||
| 	sheet_to_formulae: sheet_to_formulae, | ||||
| 	sheet_to_row_object_array: sheet_to_row_object_array | ||||
| 	sheet_to_row_object_array: sheet_to_json | ||||
| }; | ||||
| XLSX.parse_xlscfb = parse_xlscfb; | ||||
| XLSX.parse_ods = parse_ods; | ||||
| @ -14182,6 +14249,7 @@ XLSX.readFileSync = readFileSync; | ||||
| XLSX.write = writeSync; | ||||
| XLSX.writeFile = writeFileSync; | ||||
| XLSX.writeFileSync = writeFileSync; | ||||
| XLSX.writeFileAsync = writeFileAsync; | ||||
| XLSX.utils = utils; | ||||
| XLSX.CFB = CFB; | ||||
| XLSX.SSF = SSF; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user